MySQL++

Changes On Branch BOGUS
Login

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

Changes In Branch BOGUS Excluding Merge-Ins

This is equivalent to a diff from 13c05ca408 to e0025ebfb4

2018-09-26
02:37
Better explanation of "bootstrap bat" command in HACKERS.md. check-in: a75da9ed00 user: tangent tags: trunk
02:33
Not needed Closed-Leaf check-in: e0025ebfb4 user: tangent tags: BOGUS
02:28
Better explanation of the "bootstrap bat" option in HACKERS.md. BAD CHECKIN. check-in: cf53e4ee34 user: tangent tags: BOGUS
2018-07-27
06:29
Added SRPM step to RELEASE-CHECKLIST.txt check-in: 13c05ca408 user: tangent tags: trunk
06:11
More steps in RELEASE-CHECKLIST.txt. check-in: 6d331ea2d5 user: tangent tags: trunk

Changes to Bakefiles.bkgen.



1



2

3




4




5





6

7


8

9

10













11





12
13









14




15






16
17
18
19


20








21
22
23
24


<?xml version="1.0" ?>



<bakefile-gen xmlns="http://www.bakefile.org/schema/bakefile-gen">

    <input>




        ./mysql++.bkl




    </input>







    <!-- List of output formats to generate: -->


    <add-formats>

        autoconf,mingw,msvs2003prj,msvs2005prj,msvs2008prj,xcode2

    </add-formats>



















    <add-flags formats="mingw">
        -o$(INPUT_FILE_DIR)/Makefile.mingw









    </add-flags>




	<add-flags formats="msvs2003prj">






		-ovc2003/mysql++.sln
	</add-flags>
	<add-flags formats="msvs2005prj">
		-ovc2005/mysql++.sln


	</add-flags>








	<add-flags formats="msvs2008prj">
		-ovc2008/mysql++.sln -DMSVS_PLATFORMS=win64
	</add-flags>
</bakefile-gen>
>
>
|
>
>
>
|
>
|
>
>
>
>
|
>
>
>
>
|
>
>
>
>
>

>
|
>
>
|
>
|
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
>
>
>
>
|
<
>
>
>
>
>
>
>
>
>
|
>
>
>
>
|
>
>
>
>
>
>
|
|
|
<
>
>
|
>
>
>
>
>
>
>
>
|
|
|
<
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
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
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78

79
80
81
82
83
84
85
86
87
88
89
90
91
92

/***********************************************************************
 sql_buffer.cpp - Implements the SQLBuffer class.

 Copyright (c) 2007-2008 by Educational Technology Resources, Inc.
 Others may also hold copyrights on code in this file.  See the
 CREDITS.txt file in the top directory of the distribution for details.

 This file is part of MySQL++.

 MySQL++ is free software; you can redistribute it and/or modify it
 under the terms of the GNU Lesser General Public License as published
 by the Free Software Foundation; either version 2.1 of the License, or
 (at your option) any later version.

 MySQL++ is distributed in the hope that it will be useful, but WITHOUT
 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
 License for more details.

 You should have received a copy of the GNU Lesser General Public
 License along with MySQL++; if not, write to the Free Software
 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
 USA
***********************************************************************/

#include "sql_buffer.h"

#include "datetime.h"
#include "sql_types.h"

#include <string.h>

namespace mysqlpp {


SQLBuffer&
SQLBuffer::assign(const char* data, size_type length, mysql_type_info type,
		bool is_null)
{
	replace_buffer(data, length);
	type_ = type;
	is_null_ = is_null;
	return *this;
}

SQLBuffer&
SQLBuffer::assign(const std::string& s, mysql_type_info type, bool is_null)
{
	replace_buffer(s.data(), s.length());
	type_ = type;
	is_null_ = is_null;
	return *this;
}


bool
SQLBuffer::quote_q() const
{
	if ((type_.base_type().c_type() == typeid(mysqlpp::sql_datetime)) &&
			data_ && (length_ >= 5) && (memcmp(data_, "NOW()", 5) == 0)) {
		// The default DATETIME value is special-cased as a call to the
		// SQL NOW() function, which must not be quoted.
		return false;
	}
	else {
		// Normal case: we can infer the need to quote from the type.
		return type_.quote_q();
	}
}

void
SQLBuffer::replace_buffer(const char* pd, size_type length)
{
	delete[] data_;
	data_ = 0;
	length_ = 0;

	if (pd) {
		// The casts for the data member are because the C type system

		// can't distinguish initialization from modification when it
		// happens in 2 steps like this.
		// 
		// We cast away const for pd in case we're on a system that uses
		// the old definition of memcpy() with non-const 2nd parameter.
		data_ = new char[length + 1];
		length_ = length;
		memcpy(const_cast<char*>(data_), const_cast<char*>(pd), length_);
		const_cast<char*>(data_)[length_] = '\0';
	}
}

} // end namespace mysqlpp


Changes to COPYING.txt.




1



2

3




4






























































5
6


















7
8









9



















10




























The MySQL++ library proper and the reference manual derived from



comments in the library source code are licensed under the GNU Lesser

General Public License. A copy is provided in this directory, in the




file LICENSE.txt.































































The MySQL++ User Manual is licensed under a unique license derived from


















the Linux Documentation Project License. (The only changes are due to
the fact that the User Manual isn't actually part of the LDP, so a lot









of the language in the LDPL doesn't make sense when applied to the user



















manual.)  This license is provided in the file doc/userman/LICENSE.txt.

























>
>
>
|
>
>
>
|
>
|
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
|
>
>
>
>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
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
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
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
144
145
146
147
148
149
150
151
152
153
154
/***********************************************************************
 test/uds.cpp - Tests the Unix domain socket verifier in
 	UnixDomainSocketConnection.  This test always succeeds on Windows!

 Copyright (c) 2007-2008 by Educational Technology Resources, Inc.
 Others may also hold copyrights on code in this file.  See the
 CREDITS file in the top directory of the distribution for details.

 This file is part of MySQL++.

 MySQL++ is free software; you can redistribute it and/or modify it
 under the terms of the GNU Lesser General Public License as published
 by the Free Software Foundation; either version 2.1 of the License, or
 (at your option) any later version.

 MySQL++ is distributed in the hope that it will be useful, but WITHOUT
 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
 License for more details.

 You should have received a copy of the GNU Lesser General Public
 License along with MySQL++; if not, write to the Free Software
 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
 USA
***********************************************************************/

#include <connection.h>
#include <exceptions.h>

#include <iostream>
#include <sstream>
#include <string>

#if !defined(MYSQLPP_PLATFORM_WINDOWS)
#include <unistd.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/socket.h>
#include <sys/un.h>

#include <errno.h>

static const char* success_path = "test_uds_success.sock";
static const char* failure_path = "test_uds_failure.sock";

static int
make_socket(const char* path, mode_t mode)
{
	// Just in case a socket with this name exists already, try to
	// remove it.  Only a failure if it exists and we can't remove it.
	if ((unlink(path) < 0) && (errno != ENOENT)) {
		return -1;
	}

	// Create the domain socket
	int fd = socket(AF_LOCAL, SOCK_STREAM, 0);
	if (fd < 0) {
		return -1;
	}
	
	// Bind the socket to the named file
	struct sockaddr_un sun;
	memset(&sun, sizeof(sun), 0);
	sun.sun_family = AF_LOCAL;
	strncpy(sun.sun_path, path, sizeof(sun.sun_path));
	sun.sun_path[sizeof(sun.sun_path) - 1] = '\0';
	if (bind(fd, reinterpret_cast<sockaddr*>(&sun), sizeof(sun)) < 0) {
		return -1;
	}

	// Change the socket's mode as requested
	if (chmod(path, mode) < 0) {
		return -1;
	}

	return fd;
}

	
static void
test_success()
{
	std::string error;
	int fd = make_socket(success_path, S_IREAD | S_IWRITE);
	if (fd >= 0) {
		bool fail = !mysqlpp::UnixDomainSocketConnection::is_socket(
				success_path, &error);
		if (fail) {
			throw mysqlpp::SelfTestFailed(error);
		}
	}
	else {
		std::ostringstream outs;
		outs << "Failed to create test domain socket: " << strerror(errno);
		throw mysqlpp::SelfTestFailed(outs.str());
	}
}


static void
test_failure()
{
	int fd = make_socket(failure_path, S_IREAD);
	if (fd < 0) {
		std::ostringstream outs;
		outs << "Failed to create test domain socket: " << strerror(errno);
		throw mysqlpp::SelfTestFailed(outs.str());
	}

	if (mysqlpp::UnixDomainSocketConnection::is_socket(failure_path)) {
		throw mysqlpp::SelfTestFailed("Failed to fail on read-only socket");
	}
	else if (mysqlpp::UnixDomainSocketConnection::is_socket(
			"BogusBogus.sock")) {
		throw mysqlpp::SelfTestFailed("Failed to fail on bad file name");
	}
	else {
		close(fd);
		unlink(failure_path);
		fd = creat(failure_path, S_IREAD | S_IWRITE);
		bool success = mysqlpp::UnixDomainSocketConnection::is_socket(
				failure_path);
		if (success) {
			throw mysqlpp::SelfTestFailed("Failed to fail on non-socket");
		}
	}
}
#endif


int
main()
{
#if defined(MYSQLPP_PLATFORM_WINDOWS)
	// Test not appropriate to this platform.  Always succeed.
	return 0;
#else
	try {
		test_success();
		unlink(success_path);
		test_failure();
		unlink(failure_path);
		return 0;
	}
	catch (mysqlpp::SelfTestFailed& e) {
		std::cerr << "TCP address parse error: " << e.what() << std::endl;
		return 1;
	}
	catch (std::exception& e) {
		std::cerr << "Unexpected test failure: " << e.what() << std::endl;
		return 2;
	}
#endif
}

Changes to HACKERS.md.

162
163
164
165
166
167
168
169

170



171
172
173

174





175











176
177
178
179
180
181
182
*   `pedantic`

    Turns on all of GCC's warnings and portability checks.  Good for
    checking changes before making a public release.

*   `bat`

    Asks `cmd.exe` to run `bootstrap.bat` for you. This is useful when

    using Cygwin just as a command shell in preference to `cmd.exe`, as



    opposed to using Cygwin to build MySQL++ using its native tools.
    Passing 'bat' stops all command line processing in the bootstrap
    script, so if you also pass some of the other options, make "`bat`"

    last.  The only options that affect the built project files and





    `Makefiles` work are the no* ones.












*   `configure` script options

    As soon as the bootstrap script sees an option that it doesn't
    understand, it stops processing the command line.  Any subsequent
    options are passed to the `configure` script. See
    [README-Unix.txt][rmu] for more on `configure` script options.







|
>
|
>
>
>
|
|
|
>
|
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>







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
191
192
193
194
195
196
197
198
199
200
201
202
203
*   `pedantic`

    Turns on all of GCC's warnings and portability checks.  Good for
    checking changes before making a public release.

*   `bat`

    Runs `bootstrap.bat` via `cmd.exe` for you, passing along equivalent
    options to any of the "*no*" options you give before it.

    None of the other options above have any effect on the generated
    build system files when you give "`bat`".  If you need those
    features, leave this option off.

    Passing `bat` stops all command line processing in the `bootstrap`
    script, so if you also pass some of the other options, "`bat`" must
    be last.
    
    The `bootstrap.bat` script is useful only when you intend to build
    MySQL++ with MinGW or Visual C++, and you are using Cygwin only as a
    command line environment.  If you intend to build MySQL++ with
    Cygwin's GCC toolchain, you must not give this option, else you will
    not end up with the necessary build system files.

    One advantage of this feature is that the commands necessary to
    achieve a given effect with `bootstrap.bat` when run via `bootstrap`
    are shorter than when you run the batch file directly.

    Another advantage is that this low-strength version of the bootstrap
    script runs faster than the full-strength form, because it produces
    fewer files.

    Finally, running `bootstrap.bat` indirectly like this lets you avoid
    using `cmd.exe`, a command shell greatly inferior to any of those
    available for Cygwin.

*   `configure` script options

    As soon as the bootstrap script sees an option that it doesn't
    understand, it stops processing the command line.  Any subsequent
    options are passed to the `configure` script. See
    [README-Unix.txt][rmu] for more on `configure` script options.

Changes to INSTALL.txt.




1



2

3




4



5
6





7

8


9
10


11



12
13
14









15
16








The installation procedure depends on the compiler you use to build



MySQL++ and the OS you build it on.  There are platform-specific

instructions for all popular platforms:








	README-Cygwin.txt     - for Cygwin
	README-Linux.txt      - for Linux





	README-Mac-OS-X.txt   - for Mac OS X

	README-MinGW.txt      - for MinGW


	README-Solaris.txt    - for Solaris
	README-Visual-C++.txt - for Visual C++






If you're on some Unix variant (Linux, OS X, *BSD, Solaris, Cygwin...)
there are additional general instructions in README-Unix.txt.










See the main README.txt file for high-level instructions that apply
to all platforms MySQL++ works on.





>
>
>
|
>
>
>
|
>
|
>
>
>
>

>
>
>
|
|
>
>
>
>
>
|
>
|
>
>
|
|
>
>
|
>
>
>
|
<
|
>
>
>
>
>
>
>
>
>
|
<
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
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
/***********************************************************************
 test/wnp.cpp - Tests WindowsNamedPipeConnection::is_wnp().  This test
	can only fail on Windows!  It succeeds when built for anything else.

 Copyright (c) 2007 by Educational Technology Resources, Inc.
 Others may also hold copyrights on code in this file.  See the
 CREDITS file in the top directory of the distribution for details.

 This file is part of MySQL++.

 MySQL++ is free software; you can redistribute it and/or modify it
 under the terms of the GNU Lesser General Public License as published
 by the Free Software Foundation; either version 2.1 of the License, or
 (at your option) any later version.

 MySQL++ is distributed in the hope that it will be useful, but WITHOUT
 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
 License for more details.

 You should have received a copy of the GNU Lesser General Public
 License along with MySQL++; if not, write to the Free Software
 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
 USA
***********************************************************************/

#include <mysql++.h>

#include <iostream>
#include <sstream>


int
main()
{
#if defined(MYSQLPP_PLATFORM_WINDOWS)
	if (!mysqlpp::WindowsNamedPipeConnection::is_wnp(".")) {
		std::cerr << "Failed to identify Windows named pipe" << std::endl;
	

	}
	else if (mysqlpp::WindowsNamedPipeConnection::is_wnp("bogus")) {
		std::cerr << "Failed to fail for bogus named pipe" << std::endl;
	}
	else if (mysqlpp::WindowsNamedPipeConnection::is_wnp(0)) {
		std::cerr << "Failed to fail for null named pipe" << std::endl;
	}
	else {
		return 0;
	}


	return 1;
#else
	return 0;
#endif
}

Changes to LICENSE.txt.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
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
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
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
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
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
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
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
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
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
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435


436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
		  GNU LESSER GENERAL PUBLIC LICENSE
		       Version 2.1, February 1999

 Copyright (C) 1991, 1999 Free Software Foundation, Inc.
     51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 Everyone is permitted to copy and distribute verbatim copies
 of this license document, but changing it is not allowed.

[This is the first released version of the Lesser GPL.  It also counts
 as the successor of the GNU Library Public License, version 2, hence
 the version number 2.1.]

			    Preamble

  The licenses for most software are designed to take away your
freedom to share and change it.  By contrast, the GNU General Public
Licenses are intended to guarantee your freedom to share and change
free software--to make sure the software is free for all its users.

  This license, the Lesser General Public License, applies to some
specially designated software packages--typically libraries--of the
Free Software Foundation and other authors who decide to use it.  You
can use it too, but we suggest you first think carefully about whether
this license or the ordinary General Public License is the better
strategy to use in any particular case, based on the explanations below.

  When we speak of free software, we are referring to freedom of use,
not price.  Our General Public Licenses are designed to make sure that
you have the freedom to distribute copies of free software (and charge
for this service if you wish); that you receive source code or can get
it if you want it; that you can change the software and use pieces of
it in new free programs; and that you are informed that you can do
these things.

  To protect your rights, we need to make restrictions that forbid
distributors to deny you these rights or to ask you to surrender these
rights.  These restrictions translate to certain responsibilities for
you if you distribute copies of the library or if you modify it.

  For example, if you distribute copies of the library, whether gratis
or for a fee, you must give the recipients all the rights that we gave
you.  You must make sure that they, too, receive or can get the source
code.  If you link other code with the library, you must provide
complete object files to the recipients, so that they can relink them
with the library after making changes to the library and recompiling
it.  And you must show them these terms so they know their rights.

  We protect your rights with a two-step method: (1) we copyright the
library, and (2) we offer you this license, which gives you legal
permission to copy, distribute and/or modify the library.

  To protect each distributor, we want to make it very clear that
there is no warranty for the free library.  Also, if the library is
modified by someone else and passed on, the recipients should know
that what they have is not the original version, so that the original
author's reputation will not be affected by problems that might be
introduced by others.

  Finally, software patents pose a constant threat to the existence of
any free program.  We wish to make sure that a company cannot
effectively restrict the users of a free program by obtaining a
restrictive license from a patent holder.  Therefore, we insist that
any patent license obtained for a version of the library must be
consistent with the full freedom of use specified in this license.

  Most GNU software, including some libraries, is covered by the
ordinary GNU General Public License.  This license, the GNU Lesser
General Public License, applies to certain designated libraries, and
is quite different from the ordinary General Public License.  We use
this license for certain libraries in order to permit linking those
libraries into non-free programs.

  When a program is linked with a library, whether statically or using
a shared library, the combination of the two is legally speaking a
combined work, a derivative of the original library.  The ordinary
General Public License therefore permits such linking only if the
entire combination fits its criteria of freedom.  The Lesser General
Public License permits more lax criteria for linking other code with
the library.

  We call this license the "Lesser" General Public License because it
does Less to protect the user's freedom than the ordinary General
Public License.  It also provides other free software developers Less
of an advantage over competing non-free programs.  These disadvantages
are the reason we use the ordinary General Public License for many
libraries.  However, the Lesser license provides advantages in certain
special circumstances.

  For example, on rare occasions, there may be a special need to
encourage the widest possible use of a certain library, so that it becomes
a de-facto standard.  To achieve this, non-free programs must be
allowed to use the library.  A more frequent case is that a free
library does the same job as widely used non-free libraries.  In this
case, there is little to gain by limiting the free library to free
software only, so we use the Lesser General Public License.

  In other cases, permission to use a particular library in non-free
programs enables a greater number of people to use a large body of
free software.  For example, permission to use the GNU C Library in
non-free programs enables many more people to use the whole GNU
operating system, as well as its variant, the GNU/Linux operating
system.

  Although the Lesser General Public License is Less protective of the
users' freedom, it does ensure that the user of a program that is
linked with the Library has the freedom and the wherewithal to run
that program using a modified version of the Library.

  The precise terms and conditions for copying, distribution and
modification follow.  Pay close attention to the difference between a
"work based on the library" and a "work that uses the library".  The
former contains code derived from the library, whereas the latter must
be combined with the library in order to run.

		  GNU LESSER GENERAL PUBLIC LICENSE
   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION

  0. This License Agreement applies to any software library or other
program which contains a notice placed by the copyright holder or
other authorized party saying it may be distributed under the terms of
this Lesser General Public License (also called "this License").
Each licensee is addressed as "you".

  A "library" means a collection of software functions and/or data
prepared so as to be conveniently linked with application programs
(which use some of those functions and data) to form executables.

  The "Library", below, refers to any such software library or work
which has been distributed under these terms.  A "work based on the
Library" means either the Library or any derivative work under
copyright law: that is to say, a work containing the Library or a
portion of it, either verbatim or with modifications and/or translated
straightforwardly into another language.  (Hereinafter, translation is
included without limitation in the term "modification".)

  "Source code" for a work means the preferred form of the work for
making modifications to it.  For a library, complete source code means
all the source code for all modules it contains, plus any associated
interface definition files, plus the scripts used to control compilation
and installation of the library.

  Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope.  The act of
running a program using the Library is not restricted, and output from
such a program is covered only if its contents constitute a work based
on the Library (independent of the use of the Library in a tool for
writing it).  Whether that is true depends on what the Library does
and what the program that uses the Library does.
  
  1. You may copy and distribute verbatim copies of the Library's
complete source code as you receive it, in any medium, provided that
you conspicuously and appropriately publish on each copy an
appropriate copyright notice and disclaimer of warranty; keep intact
all the notices that refer to this License and to the absence of any
warranty; and distribute a copy of this License along with the
Library.

  You may charge a fee for the physical act of transferring a copy,
and you may at your option offer warranty protection in exchange for a
fee.

  2. You may modify your copy or copies of the Library or any portion
of it, thus forming a work based on the Library, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:

    a) The modified work must itself be a software library.

    b) You must cause the files modified to carry prominent notices
    stating that you changed the files and the date of any change.

    c) You must cause the whole of the work to be licensed at no
    charge to all third parties under the terms of this License.

    d) If a facility in the modified Library refers to a function or a
    table of data to be supplied by an application program that uses
    the facility, other than as an argument passed when the facility
    is invoked, then you must make a good faith effort to ensure that,
    in the event an application does not supply such function or
    table, the facility still operates, and performs whatever part of
    its purpose remains meaningful.

    (For example, a function in a library to compute square roots has
    a purpose that is entirely well-defined independent of the
    application.  Therefore, Subsection 2d requires that any
    application-supplied function or table used by this function must
    be optional: if the application does not supply it, the square
    root function must still compute square roots.)

These requirements apply to the modified work as a whole.  If
identifiable sections of that work are not derived from the Library,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works.  But when you
distribute the same sections as part of a whole which is a work based
on the Library, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote
it.

Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Library.

In addition, mere aggregation of another work not based on the Library
with the Library (or with a work based on the Library) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.

  3. You may opt to apply the terms of the ordinary GNU General Public
License instead of this License to a given copy of the Library.  To do
this, you must alter all the notices that refer to this License, so
that they refer to the ordinary GNU General Public License, version 2,
instead of to this License.  (If a newer version than version 2 of the
ordinary GNU General Public License has appeared, then you can specify
that version instead if you wish.)  Do not make any other change in
these notices.

  Once this change is made in a given copy, it is irreversible for
that copy, so the ordinary GNU General Public License applies to all
subsequent copies and derivative works made from that copy.

  This option is useful when you wish to copy part of the code of
the Library into a program that is not a library.

  4. You may copy and distribute the Library (or a portion or
derivative of it, under Section 2) in object code or executable form
under the terms of Sections 1 and 2 above provided that you accompany
it with the complete corresponding machine-readable source code, which
must be distributed under the terms of Sections 1 and 2 above on a
medium customarily used for software interchange.

  If distribution of object code is made by offering access to copy
from a designated place, then offering equivalent access to copy the
source code from the same place satisfies the requirement to
distribute the source code, even though third parties are not
compelled to copy the source along with the object code.

  5. A program that contains no derivative of any portion of the
Library, but is designed to work with the Library by being compiled or
linked with it, is called a "work that uses the Library".  Such a
work, in isolation, is not a derivative work of the Library, and
therefore falls outside the scope of this License.

  However, linking a "work that uses the Library" with the Library
creates an executable that is a derivative of the Library (because it
contains portions of the Library), rather than a "work that uses the
library".  The executable is therefore covered by this License.
Section 6 states terms for distribution of such executables.


  When a "work that uses the Library" uses material from a header file
that is part of the Library, the object code for the work may be a
derivative work of the Library even though the source code is not.
Whether this is true is especially significant if the work can be
linked without the Library, or if the work is itself a library.  The
threshold for this to be true is not precisely defined by law.

  If such an object file uses only numerical parameters, data
structure layouts and accessors, and small macros and small inline
functions (ten lines or less in length), then the use of the object
file is unrestricted, regardless of whether it is legally a derivative
work.  (Executables containing this object code plus portions of the
Library will still fall under Section 6.)

  Otherwise, if the work is a derivative of the Library, you may
distribute the object code for the work under the terms of Section 6.
Any executables containing that work also fall under Section 6,
whether or not they are linked directly with the Library itself.

  6. As an exception to the Sections above, you may also combine or
link a "work that uses the Library" with the Library to produce a
work containing portions of the Library, and distribute that work
under terms of your choice, provided that the terms permit
modification of the work for the customer's own use and reverse
engineering for debugging such modifications.

  You must give prominent notice with each copy of the work that the
Library is used in it and that the Library and its use are covered by
this License.  You must supply a copy of this License.  If the work
during execution displays copyright notices, you must include the
copyright notice for the Library among them, as well as a reference
directing the user to the copy of this License.  Also, you must do one
of these things:

    a) Accompany the work with the complete corresponding
    machine-readable source code for the Library including whatever
    changes were used in the work (which must be distributed under
    Sections 1 and 2 above); and, if the work is an executable linked
    with the Library, with the complete machine-readable "work that
    uses the Library", as object code and/or source code, so that the
    user can modify the Library and then relink to produce a modified
    executable containing the modified Library.  (It is understood
    that the user who changes the contents of definitions files in the
    Library will not necessarily be able to recompile the application
    to use the modified definitions.)

    b) Use a suitable shared library mechanism for linking with the
    Library.  A suitable mechanism is one that (1) uses at run time a
    copy of the library already present on the user's computer system,
    rather than copying library functions into the executable, and (2)
    will operate properly with a modified version of the library, if
    the user installs one, as long as the modified version is
    interface-compatible with the version that the work was made with.

    c) Accompany the work with a written offer, valid for at
    least three years, to give the same user the materials
    specified in Subsection 6a, above, for a charge no more
    than the cost of performing this distribution.

    d) If distribution of the work is made by offering access to copy
    from a designated place, offer equivalent access to copy the above
    specified materials from the same place.

    e) Verify that the user has already received a copy of these
    materials or that you have already sent this user a copy.

  For an executable, the required form of the "work that uses the
Library" must include any data and utility programs needed for
reproducing the executable from it.  However, as a special exception,
the materials to be distributed need not include anything that is
normally distributed (in either source or binary form) with the major
components (compiler, kernel, and so on) of the operating system on
which the executable runs, unless that component itself accompanies
the executable.

  It may happen that this requirement contradicts the license
restrictions of other proprietary libraries that do not normally
accompany the operating system.  Such a contradiction means you cannot
use both them and the Library together in an executable that you
distribute.

  7. You may place library facilities that are a work based on the
Library side-by-side in a single library together with other library
facilities not covered by this License, and distribute such a combined
library, provided that the separate distribution of the work based on
the Library and of the other library facilities is otherwise
permitted, and provided that you do these two things:

    a) Accompany the combined library with a copy of the same work
    based on the Library, uncombined with any other library
    facilities.  This must be distributed under the terms of the
    Sections above.

    b) Give prominent notice with the combined library of the fact
    that part of it is a work based on the Library, and explaining
    where to find the accompanying uncombined form of the same work.


  8. You may not copy, modify, sublicense, link with, or distribute
the Library except as expressly provided under this License.  Any
attempt otherwise to copy, modify, sublicense, link with, or

distribute the Library is void, and will automatically terminate your
rights under this License.  However, parties who have received copies,
or rights, from you under this License will not have their licenses
terminated so long as such parties remain in full compliance.


  9. You are not required to accept this License, since you have not
signed it.  However, nothing else grants you permission to modify or
distribute the Library or its derivative works.  These actions are

prohibited by law if you do not accept this License.  Therefore, by
modifying or distributing the Library (or any work based on the
Library), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying

the Library or works based on it.

  10. Each time you redistribute the Library (or any work based on the
Library), the recipient automatically receives a license from the

original licensor to copy, distribute, link with or modify the Library
subject to these terms and conditions.  You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties with
this License.

  11. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License.  If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Library at all.  For example, if a patent
license would not permit royalty-free redistribution of the Library by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Library.

If any portion of this section is held invalid or unenforceable under any
particular circumstance, the balance of the section is intended to apply,
and the section as a whole is intended to apply in other circumstances.

It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system which is
implemented by public license practices.  Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.

This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.

  12. If the distribution and/or use of the Library is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Library under this License may add
an explicit geographical distribution limitation excluding those countries,
so that distribution is permitted only in or among countries not thus
excluded.  In such case, this License incorporates the limitation as if
written in the body of this License.

  13. The Free Software Foundation may publish revised and/or new
versions of the Lesser General Public License from time to time.
Such new versions will be similar in spirit to the present version,
but may differ in detail to address new problems or concerns.

Each version is given a distinguishing version number.  If the Library
specifies a version number of this License which applies to it and
"any later version", you have the option of following the terms and
conditions either of that version or of any later version published by
the Free Software Foundation.  If the Library does not specify a
license version number, you may choose any version ever published by
the Free Software Foundation.

  14. If you wish to incorporate parts of the Library into other free
programs whose distribution conditions are incompatible with these,
write to the author to ask for permission.  For software which is
copyrighted by the Free Software Foundation, write to the Free
Software Foundation; we sometimes make exceptions for this.  Our
decision will be guided by the two goals of preserving the free status
of all derivatives of our free software and of promoting the sharing
and reuse of software generally.

			    NO WARRANTY



  15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
LIBRARY IS WITH YOU.  SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.

  16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
DAMAGES.

		     END OF TERMS AND CONDITIONS

           How to Apply These Terms to Your New Libraries

  If you develop a new library, and you want it to be of the greatest
possible use to the public, we recommend making it free software that
everyone can redistribute and change.  You can do so by permitting
redistribution under these terms (or, alternatively, under the terms of the
ordinary General Public License).

  To apply these terms, attach the following notices to the library.  It is
safest to attach them to the start of each source file to most effectively
convey the exclusion of warranty; and each file should have at least the
"copyright" line and a pointer to where the full notice is found.

    <one line to give the library's name and a brief idea of what it does.>
    Copyright (C) <year>  <name of author>

    This library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Lesser General Public
    License as published by the Free Software Foundation; either
    version 2.1 of the License, or (at your option) any later version.

    This library is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    Lesser General Public License for more details.

    You should have received a copy of the GNU Lesser General Public
    License along with this library; if not, write to the Free Software
    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA

Also add information on how to contact you by electronic and paper mail.

You should also get your employer (if you work as a programmer) or your
school, if any, to sign a "copyright disclaimer" for the library, if
necessary.  Here is a sample; alter the names:

  Yoyodyne, Inc., hereby disclaims all copyright interest in the
  library `Frob' (a library for tweaking knobs) written by James Random Hacker.

  <signature of Ty Coon>, 1 April 1990
  Ty Coon, President of Vice

That's all there is to it!


<
<
|
<
<
<
<
|
<
<
<

<
|
<
<
<
<
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<

<
<
<
<
<
<
|
<
<
<
|
<
<
<
|
<
|
<
<
<
<
<
|
<
<
<
<
<
<
<
|
<
<
<
<
<
<
|
<
<
<
<
|
<
<
<
<
<
|
<
<
|
<
<
<
<
<
|
<
<
<

<
<
<
<
<
<
<
|
<
<
<
<
<
|
<
<
<
<
<
<
<
|
<
<
<
<
<
<
<
|
<
<
<
|
<
<
<
<
|
<
|
<
<
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<

<
<
<
<
|
<
<
<
<
|
<
<
<
<
<
<
<
<
|
<
<
<
|
<
<
|
<
<
<
<
<
<
|
<
<
<
<
<
|
<
<
<
<
<
|
<
<
<
<
<
>
|
<
<
<
<
<
<

<
<
<
<
<
<
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<

>
|
|
<
>
|
|
|
<
|
>
|
|
<
>
|
|
|
<
>
|
|
|
<
>
|
|
|
<
<
|
<
<
<
<
<
<
<
<
<
<
<
<

<
<
<
|
<
<
<
<
<
<
<
<
<
<
|
<
<
|
<
<
<
<
<
<
<
|
<
<
<
<
|
<
<
<
<
<
<
<
|
<
<
<
<
<
<
<
<
|
<
>
>
|
<
<
<
<
<
<
<
<
<

<
<
<
<
<
<
<
<
<
<
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<


1




2



3

4




5













































6






7



8



9

10





11







12






13




14





15


16





17



18







19





20







21







22



23




24

25


26




























27




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

56
57
58
59

60
61
62
63


64












65



66










67


68







69




70







71








72

73
74
75









76










77

















































#ifndef __compare1_hh__




#define __compare1_hh__





#include <function.h>




#include "row1.hh"




















































template <class BinaryPred, class CmpType>



class MysqlCmp : public unary_function<const MysqlRow&, bool>



{

protected:





  unsigned int index;







  BinaryPred   func;






  CmpType      cmp2;




public:





  MysqlCmp(uint i, const BinaryPred &f, const CmpType &c) : index(i),func(f),cmp2(c) {}


  bool operator () (const MysqlRow& cmp1) const {return func(cmp2,cmp1[index]);}





};











template <class BinaryPred>





class MysqlCmpCStr : public MysqlCmp<BinaryPred, const char *>







{







public:



  MysqlCmpCStr(uint i, const BinaryPred &f, const char* c) : MysqlCmp(i,f,c) {}




  bool operator () (const MysqlRow& cmp1) const 

    {return func(cmp2,cmp1[index]);}


};

































//: A special function for using in find_if function where i is the field index number.




// This is a more generic form of mysql_cmp_cstr will work with any








// CmpType that MysqlString can convert to.  However, this is not



// neary as effecent.  Only use when obsoletely nessary.


template <class BinaryPred, class CmpType>






MysqlCmp <BinaryPred, CmpType>





mysql_cmp(uint i, const BinaryPred &func, const CmpType &cmp2)





{





  return MysqlCmp<BinaryPred, CmpType>(i, func, cmp2);
}













typedef binary_function<const char*, const char*, bool> bin_char_pred;



















































































struct cstr_equal_to : bin_char_pred {
  bool operator () (const char *x, const char *y) const
    {return !strcmp(x,y);}

};
struct cstr_not_equal_to : bin_char_pred {
  bool operator () (const char *x, const char *y) const
    {return strcmp(x,y);}

};
struct cstr_less : bin_char_pred {
  bool operator () (const char *x, const char *y) const
    {return strcmp(x,y) > 0; }

};
struct cstr_less_equal : bin_char_pred {
  bool operator () (const char *x, const char *y) const
    {return strcmp(x,y) >= 0; }

};
struct cstr_greater : bin_char_pred {
  bool operator () (const char *x, const char *y) const
    {return strcmp(x,y) < 0; }

};
struct cstr_greater_equal : bin_char_pred {
  bool operator () (const char *x, const char *y) const
    {return strcmp(x,y) <= 0; }


};
















//:A special function for using in find_if fucntion where i is the field index










//:number.


//







// func should be one of cstr_equal_to(), cstr_not_equal_to(),




// cstr_less(), cstr_less_equal(), cstr_less_equal(), cstr_less_equal().







template <class BinaryPred>








MysqlCmpCStr <BinaryPred>

mysql_cmp_cstr (uint i, const BinaryPred &func, const char *cmp2) {
  return MysqlCmpCStr<BinaryPred>(i, func, cmp2);
}




















#endif















































Changes to README-Linux.txt.

1
2
3
4
5
6

7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26

27
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
56
57
58
59
60
61
62
63
64
65
66
67
68



69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
Linux is basically Unix, so README-Unix.txt covers the generic bits.
I'll just cover a few of the issues specific to Linux here.


Prerequisite: Install the MySQL Development Files
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

    MySQL++ is built on top of the MySQL C API library, so it needs the
    C API development files to build against.  Most distributions of
    the MySQL server for Linux don't come with these development files;
    they're packaged separately.  This is because you don't actually
    need the server on your development machine, though it's often more
    convenient to use a local server than a remote one, for testing.

    There are about as many different ways to get the C API development
    files on your system as there are major Linux distributions.
    More actually, because you also have the option of the official
    MySQL binaries from mysql.com:

        http://dev.mysql.com/downloads/mysql/5.0.html#linux

    For RPM-based distributions, MySQL comes in several different
    packages.  You need at least the -devel and the -shared packages
    to build MySQL++.

    The other binary distributions seem to come in just a single file,
    presumably with everything included.


    You can also build from source, in which case you will also get
    the entire kit and kaboodle.

    MySQL frequently comes with Linux distributions as well.  If your
    distribution doesn't come with at least MySQL v4.1, I recommend
    using the official MySQL.com packages instead.  MySQL++ can be
    made to run with 4.0 and older, but it takes some work.

    On Red Hat type systems with yum, say:

        # yum install mysql-devel

    If you want to use rpm directly, you need that package and probably
    the base mysql package as well.



    On Debian/Ubuntu type systems, say:


        $ sudo apt-get install libmysqlclient15-dev

    The version number is the ABI version of the MySQL C API library.
    ABI version 15 corresponds to MySQL version 5.0, the recommended
    stable version as of this writing.

        

Dealing with the Dynamic Linker, ld.so
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

    ld.so is a system-level program on Linux which is used to run any
    program that uses shared libraries (lib*.so).  Its job is to find
    the libraries and link them to the base executable so it will run.

    Because ld.so only looks in a few places for libraries on most
    systems, a common problem is a program that builds without error
    but won't run, complaining about libmysqlpp.SOMETHING.

    There are a number of ways to deal with this.

    First, you could just configure MySQL++ to install under /usr
    instead of /usr/local, like system-provided packages:

        $ ./configure --prefix=/usr




    This isn't recommended practice when building packages from source,
    but it does work.

    Second, you can add the MySQL++ library directory to the
    LD_LIBRARY_PATH environment variable.  This works like the shell's
    PATH variable: a colon-separated list of directories to search.
    This is best when the installation directory is something totally
    uncommon, or you don't have root permissions on the box so you
    can't do the next option.

    Finally, the most robust way to tell ld.so about a nonstandard
    library directory is to put it in /etc/ld.so.conf or in one of
    the files included from there.  Then, run ldconfig as root to
    rebuild the cache file ld.so uses to find libraries in these
    nonstandard directories.  Running ldconfig isn't necessary for
    the previous two methods.
|
|
|
|
|
<
>
|
|
|
<
<
<

<
<
<
|
|
<
|
<
<
<
|
<
<
>

<
|
|
<
<
<
<
|
<
|
<

<
|
|
>
>
<

>
|
|
|
|
<

|
>
|
<
>
|
|
<

<
<
<
|
<
|
<
<

<

>
>
>
|
|
|
|
|
|
|
|
<
|
<
<
<
<
<
<
1
2
3
4
5

6
7
8
9



10



11
12

13



14


15
16

17
18




19

20

21

22
23
24
25

26
27
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






<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE article PUBLIC "-//OASIS//DTD DocBook XML V4.3//EN"
                         "http://www.docbook.org/xml/4.3/docbookx.dtd"
[ <!ENTITY % xinclude SYSTEM "xinclude.mod">
%xinclude;

]>
<article>
	<articleinfo>
		<title>MySQL++ v3.0.8 User Manual</title>







		<authorgroup>
			<author>

				<firstname>Kevin</firstname>



				<surname>Atkinson</surname>


			</author>


			<author>
				<firstname>Sinisa</firstname>




				<surname>Milivojevic</surname>

			</author>



			<author>
				<firstname>Monty</firstname>
				<surname>Widenius</surname>
			</author>


			<author>
				<firstname>Warren</firstname>
				<surname>Young</surname>
			</author>
		</authorgroup>


		<copyright>
			<year>1998-2001, 2005-2008</year>
			<holder>Kevin Atkinson (original author)</holder>

			<holder>MySQL AB</holder>
			<holder>Educational Technology Resources</holder>
		</copyright>





		<pubdate><?dbtimestamp format="B d, Y"?></pubdate>

	</articleinfo>





	<xi:include href="intro.dbx" xmlns:xi="http://www.w3.org/2001/XInclude"/>
	<xi:include href="overview.dbx" xmlns:xi="http://www.w3.org/2001/XInclude"/>
	<xi:include href="tutorial.dbx" xmlns:xi="http://www.w3.org/2001/XInclude"/>
	<xi:include href="tquery.dbx" xmlns:xi="http://www.w3.org/2001/XInclude"/>
	<xi:include href="ssqls.dbx" xmlns:xi="http://www.w3.org/2001/XInclude"/>
	<xi:include href="unicode.dbx" xmlns:xi="http://www.w3.org/2001/XInclude"/>
	<xi:include href="threads.dbx" xmlns:xi="http://www.w3.org/2001/XInclude"/>
	<xi:include href="configuration.dbx" xmlns:xi="http://www.w3.org/2001/XInclude"/>
	<xi:include href="incorporating.dbx" xmlns:xi="http://www.w3.org/2001/XInclude"/>
	<xi:include href="breakages.dbx" xmlns:xi="http://www.w3.org/2001/XInclude"/>
	<xi:include href="licenses.dbx" xmlns:xi="http://www.w3.org/2001/XInclude"/>

</article>






Changes to README-Mac-OS-X.txt.

1
2
3
4


5
6
7
8
9


10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
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
56
57
58
59
60
61
62
63
64
65
66
67

68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87


88
89


90
91


92
93
94
95
96
97
98
99
100
101


102
103
104
105
106

107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122

123
124
125
126
127
128
129
130
131
132
133
134
Building MySQL++
~~~~~~~~~~~~~~~~
    There are two major ways to build MySQL++: from the command line, or
    from within the Xcode IDE.



    MySQL++ has its roots in Unix and Linux, like MySQL itself.  As a
    result, the most well-supported way to build MySQL++ is from the
    command line, or Terminal as Apple likes to call it.  See
    README-Unix.txt for the generic instructions.  Further Mac-specific


    details are given elsewhere in this file.

    The option to build MySQL++ from within Xcode is new.  We added
    experimental support for it in 3.0.0, but it didn't actually get
    tested and debugged until 3.1.0.  It may still be buggy, and over
    time it's more likely to break again than the command line method,
    simply because it receives less testing during development.  Even
    fully functional, it is less flexible than building from the command
    line; Xcode's project system cannot match the power available within
    the autotools build system.

    If you try the Xcode method and find that it doesn't work, the
    easiest way around that roadblock is to build from the command line
    instead.  If you're the adventurous sort and want to contribute to
    the development of MySQL++, see the file HACKERS.txt for more info
    on fixing the source file used as input in the project file
    generation process.  We don't want fixed project files, we want a
    process that lets us consistently generate correct project files.


Prerequisite: Install the MySQL Development Files
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    MySQL++ is built on top of the MySQL C API library, so for MySQL++
    to build, it needs at least that library and its header files


    installed.  You don't need the server itself installed on your
    development machine, though it's often helpful anyway, for testing.
    There are many suitable sources:

    - The simplest option is to download the MySQL server DMG from
      mysql.com.  In addition to the C API files you absolultely must
      have, this gives you a nice Mac-like installation procedure and a



      preference pane for bringing the server up and down and setting it
      to start on system boot.

    - If you really only want the C API development files, MySQL offers
      them separately as Connector/C.  As of this writing, you get the
      files as a tarball, and you have to copy its contents to some
      suitable location on your hard drive.  If you're using Xcode to

      build MySQL++, you'll want to put them under /usr/local/mysql.
      MySQL++'s command line build system is far more tolerant, looking
      there and in many other typical locations.

    - If you use Fink, you can install the C API files with:



      $ fink install mysql15-dev
      
      If you also want a local MySQL server, say this instead:

      $ fink install mysql mysql15-dev
    
    - From MacPorts, http://macports.org.  I have zero information on
      this other than that it's theoretically possible for it to work.
      If you figure out how to make it work, please post the method
      to the mailing list so I can update this document.


Dealing with the 64-Bit Transition in Snow Leopard
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

    Xcode for Snow Leopard installs two independent versions of the GNU
    Compiler Collection.  The default is GCC 4.2, and it is set up to
    build 64-bit executables by default, even if your system is booted
    into 32-bit mode.  You also get GCC 4.0, which builds 32-bit
    executables by default.  On top of that, you have the confusion
    added by Apple's decision to make all 64-bit capable machines boot
    into 32-bit mode by default, except for the Xserves.

    The first symptom most people run into as a result of this mess is
    that the "configure" script fails, yelling something about being
    unable to link to libmysqlclient, the MySQL C API client library.
    It's because the library was probably built as a 32-bit executable
    and you're using the default compiler which tries to build a 64-bit
    test executable against this library and fails.

    There are many ways out of this tarpit.  Here are the ones I prefer:

    First, you can force GCC 4.2 to build 32-bit binaries:

        ./configure CFLAGS=-m32 CXXFLAGS=-m32 LDFLAGS=-m32 --other-flags-here



    Second, you can make the MySQL++ build system use GCC 4.0 instead:



        ./configure CC=gcc-4.0 CXX=g++-4.0 --other-flags-here



    Last, you could just take Apple's implied advice and start booting
    your Mac into 64-bit mode, if it will support it.  Here's an article
    that goes into all the details:

        http://macperformanceguide.com/SnowLeopard-64bit.html

    I'm aware of other solutions to the problem, but I expect one among
    these will work for you.




Making Universal Binaries
~~~~~~~~~~~~~~~~~~~~~~~~~
    By default, the command line build system will generate libraries
    that only work with the platform you build MySQL++ on.  It can be

    convinced to build "universal" binaries instead by configuring
    the library like so:

    $ ./configure --disable-dependency-tracking \
            CXXFLAGS='-arch ppc -arch i386'

    This builds the library for the two 32-bit OS X architectures, and
    is what most people have traditionally thought of as "universal".
    However, you may also want a 64-bit build, meaning there are four
    different architectures, and thus four -arch flags needed:

    $ ./configure --disable-dependency-tracking \
            CXXFLAGS='-arch ppc -arch ppc64 -arch i386 -arch x86_64'

    These are single commands, with the line broken to keep the line
    lengths in this document reasonable.


    The first command doubles build time relative to the default
    configuration, and the second quadruples it.  It also makes the
    resulting binaries larger, which increases the amount of time
    it takes to start a program.  Build MySQL++ like this only if
    you must.

    The --disable-dependency-tracking flag is necessary because,
    when building universal binaries, it has to rebuild each source
    module multiple times, which confuses the logic that tries to tell
    when a given module needs rebuiding based on its dependencies on
    other files.
<
<
<
<
>
>

<
<
<
<
>
>
|
|
<
<
<
<
<
<
<
<

<
<
<
|
<
<
<

|
<
<
|
<
>
>
<
<
<

<
<
<
>
>
>
|
<

<
<
<
<
>
|
<
<
|
<
>
>

|
|
<

<
|
<
<
<
<
|

<
<
>
<
<
<
<
<
<
<

<
<
|
<
<
<

<
|
<

<
>
>
|
<
>
>

<
>
>
|
<
<
<
|
<

<
<

>
>
|
|
<
<
|
>
|
<
|
|
|
|
<
<
<
<
|
<
<

<
<
>
|
<
<
<
<
<

<
<
<
<
|




1
2
3




4
5
6
7








8



9



10
11


12

13
14



15



16
17
18
19

20




21
22


23

24
25
26
27
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
56
57

58
59
60
61




62


63


64
65





66




67




/***********************************************************************
 field_names.cpp - Implements the FieldNames class.





 Copyright (c) 1998 by Kevin Atkinson, (c) 1999-2001 by MySQL AB, and
 (c) 2004-2010 by Educational Technology Resources, Inc.  Others may
 also hold copyrights on code in this file.  See the CREDITS.txt file
 in the top directory of the distribution for details.












 This file is part of MySQL++.




 MySQL++ is free software; you can redistribute it and/or modify it


 under the terms of the GNU Lesser General Public License as published

 by the Free Software Foundation; either version 2.1 of the License, or
 (at your option) any later version.







 MySQL++ is distributed in the hope that it will be useful, but WITHOUT
 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
 License for more details.






 You should have received a copy of the GNU Lesser General Public
 License along with MySQL++; if not, write to the Free Software


 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301

 USA
***********************************************************************/

#define MYSQLPP_NOT_HEADER
#include "common.h"



#include "field_names.h"




#include "result.h"



#include <algorithm>










namespace mysqlpp {





namespace internal { extern void str_to_lwr(std::string& s); }



void
FieldNames::init(const ResultBase* res)
{

	size_t num = res->num_fields();
	reserve(num);


	for (size_t i = 0; i < num; i++) {
		push_back(res->fields().at(i).name());
	}



}





unsigned int
FieldNames::operator [](const std::string& s) const
{
	std::string temp1(s);


	internal::str_to_lwr(temp1);
	for (const_iterator it = begin(); it != end(); ++it) {
	std::string temp2(*it);

		internal::str_to_lwr(temp2);
		if (temp2.compare(temp1) == 0) {
			return it - begin();
		}




	}





	return end() - begin();
}










} // end namespace mysqlpp

Changes to README-MinGW.txt.

1
2
3
4
5
6
7
8
9

10
11
12
13
14
15
16
17
18



19
20



21
22
23
24
25
26
27
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
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88





89
90
91
92
93

94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
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
144
145
146

147
148

149
150

151
152
153
154
155

156
157
158
159
160
161
162
163
164
165
Prerequisite: GCC Version
~~~~~~~~~~~~~~~~~~~~~~~~~
    If your MinGW version isn't using at least GCC 3.4.5, it needs
    to be updated.  Older versions are known to not work with MySQL++.

    As of MySQL++ 3.1.1, the required version might need to be even
    newer, as we are now depending on improvements to the MinGW linker
    which probably don't go back that far.



Prerequisite: MySQL C Development Files
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    MySQL++ is built atop MySQL's C API library.  The easiest way to
    get that is to install Connector/C on your development system,
    which you can download from mysql.com.  The distribution assumes
    these files are in:

        C:\Program Files\MySQL\MySQL Connector C 6.1\




    There are a number of reasons why that path may not work for you:




      - You have a newer version of Connector/C installed

      - You're on a 64-bit system, but have the 32-bit versions of
        Connector/C and MinGW installed and wish to build a 32-bit
        binary.  In that case, the path will look like this instead:

          C:\Program Files (x86)\MySQL\MySQL Connector C 6.1\

      - You may have the MySQL Server on your system and installed the



        development files along with it, and therefore don't want to
        install Connector/C separately.  In that case, the path will


        look like this instead:

          C:\Program Files\MySQL\MySQL Server 5.6\
    
    Regardless of the reason you have for changing this path, there are
    two ways that work:

      - The easy way is to do a global search and replace on the path
        in Makefile.mingw.  This is a generated file, but if that's the

        only change to MySQL++ you need, it works fine.

      - If you're doing deeper work on MySQL++, you should change the

        MYSQL_WIN_DIR variable at the top of mysql++.bkl instead.


        
        Having done that, you can generate Makefile.mingw from that

        file using the Windows port of Bakefile (http://bakefile.org/):
        
          bakefile_gen -f mingw


Building the Library and Example Programs
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    With the prerequisites above taken care of, you can build MySQL++
    with this command:

        mingw32-make -f Makefile.mingw

    Notice that we're using the MinGW-specific version of GNU make, not
    the Cygwin or MSYS versions.  Many things will break otherwise: path
    separator handling, shell commands used by the Makefile, etc.

    Speaking of Cygwin and MSYS, if you have either these or any other
    Unix emulation environment installed, be sure their executables
    aren't in the PATH when building MySQL++.  MinGW's version of GNU
    make does some funny things if it thinks it's running in the
    presence of Unixy tools, which will break the MySQL++ build.

    Once the library is built, you should run the examples.  At minimum,
    run resetdb and simple1.

    Once you're satisfied that the library is working correctly, you can
    run install.hta to automatically install the library files and
    headers in subdirectories under c:\mysql++.


Cygwin and MinGW Coexistence
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    It's possible to have both Cygwin and MinGW installed and build
    with the MinGW tools without interference from the Cygwin bits.
    The main thing you have to take care of is that MinGW's bin
    directory must precede the Cygwin bin directory in the PATH,
    so that its tools are found first.  If you use Cygwin's bash
    as a command shell in preference to the DOS-like cmd.exe, you
    can use this shell script to temporarily set the environment to
    "MinGW mode" and make it easy to get back to "Cygwin mode":






        #!/bin/sh
        PATH=/c/mingw/bin:/c/windows:/c/windows/system32:/c/cygwin/bin
        echo "Say 'exit' to leave MinGW shell and restore Cygwin environment."
        /usr/bin/bash --rcfile ~/.mingwrc


    I recommend having at least this in the ~/.mingwrc file:

        alias make=mingw32-make
        PS1='MinGW: \W \$ '

    The prompt change reminds you that you are in a sub-shell set up for
    MinGW.  The alias for 'make' ensures you don't accidentally run
    Cygwin's make, which won't work with Makefile.mingw.  We could just
    leave /c/cygwin/bin out of the environment, but there are Cygwin
    tools we want access to, like vim.  As long as all the MinGW ones
    override those Cygwin also provides, we don't need to worry about
    having both in the PATH.  Besides, having the alias is nice for
    those who have 'make' committed to muscle memory.


Building on Linux
~~~~~~~~~~~~~~~~~
    You might wish to build MySQL++ with MinGW because you're
    not actually running Windows, but need Windows executables.
    The thought being that this lets you use GCC, the same compiler
    you're probably using to make native executables.  There are
    indeed ways to make this work.

    The most "native" way to do this is to run MinGW under Wine.
    Leonti Bielski provided these instructions:

        1. Install MinGW through Wine:

           $ wine MinGW-5.1.6.exe

        2. Add the MinGW directory to Wine's PATH with Wine regedit:


           http://winehq.org/site/docs/wineusr-guide/environment-variables

        3. Install MySQL under Wine, or at least unpack the Windows
           ZIP file version of MySQL in a place where Wine can find it.
           You don't need to run a Windows MySQL server under Wine.
           We're only doing this to get the MySQL C API library and
           its headers, which MySQL++ builds against.  The resulting
           MinGW build of MySQL++ can talk to a native MySQL server
           out in Wine's host environment or on some other machine.

        4. Modify Makefile.mingw to match the install location for
           the MySQL C API files.



        5. Build MySQL++ with:
        
           $ wine mingw32-make -f Makefile.mingw

    Another way is to build a Windows virtual machine, such as with
    VMware or VirtualBox.  In that case, you'd use the regular build
    instructions at the top of this document.


    You might think to avoid the need for Wine or Windows by use of a
    MinGW cross-compiler:


        $ ./configure --target=mingw32

        $ make

    Unfortunately, that currently doesn't work.

    The reason is that our autoconf build system assumes a

    typical POSIX type target, which MinGW is not.  We made this
    assumption because we have a perfectly good MinGW build option,
    Makefile.mingw.  But, that also won't work on a POSIX system
    because that Makefile assumes external commands run under cmd.exe,
    not some Unixy shell.  Thus the advice to build with Makefile.mingw
    under Windows or something sufficiently close to it.

    If you really wanted to, you could extend the autoconf build system
    to make it realize when it's being used to cross-compile for MinGW.
    Patches thoughtfully considered; see HACKERS.txt.
|
<
<
<

<
<
<
|
>
|
<
<
<
<
<
|

<
>
>
>

<
>
>
>

|
|
|
|
<
|
|
|
<
>
>
>
|
<
>
>
|
|
<
|
<
|
|
|
|
>
<

|
>
|
>
>
|
<
>
|
|
|
|
|
<
<
|
|
|
|
|
<
<
<
|
<
<
<
<
<
|
<
<
|
<
<
<
|
|
|
<
<
<
<
<
<
<
<
<

>
>
>
>
>
|
|
<
|
|
>
|
|
|
|
|
|
|
|
|
<
<
<
<

|
|
<
|
<
<
<
<
|
<
<

<
|
<
|
<

>
|
|
|
|
|
|
|
|
|
|
<
|
|
>
>
|
|
<
|
|
|
<

>
|
|
>

<
>
|

<
|
<
>
|
<
<
<
<
<
|
<
<
<
1



2



3
4
5





6
7

8
9
10
11

12
13
14
15
16
17
18
19

20
21
22

23
24
25
26

27
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





56


57



58
59
60









61
62
63
64
65
66
67
68

69
70
71
72
73
74
75
76
77
78
79
80




81
82
83

84




85


86

87

88

89
90
91
92
93
94
95
96
97
98
99
100

101
102
103
104
105
106

107
108
109

110
111
112
113
114
115

116
117
118

119

120
121





122



#!/bin/sh







# This script is part of Bakefile (http://www.bakefile.org) autoconf
# script. It is used to track C/C++ files dependencies in portable way.
#





# Permission is given to use this file in any way.


DEPSMODE=gcc
DEPSFLAG="-MMD"
DEPSDIRBASE=.deps


if test $DEPSMODE = gcc ; then
    $* ${DEPSFLAG}
    status=$?

    # determine location of created files:
    while test $# -gt 0; do
        case "$1" in
            -o )

                shift
                objfile=$1
            ;;

            -* )
            ;;
            * )
                srcfile=$1

            ;;
        esac
        shift
    done

    objfilebase=`basename $objfile`

    builddir=`dirname $objfile`
    depfile=`basename $srcfile | sed -e 's/\..*$/.d/g'`
    depobjname=`echo $depfile |sed -e 's/\.d/.o/g'`
    depsdir=$builddir/$DEPSDIRBASE
    mkdir -p $depsdir


    # if the compiler failed, we're done:
    if test ${status} != 0 ; then
        rm -f $depfile
        exit ${status}
    fi


    # move created file to the location we want it in:
    if test -f $depfile ; then
        sed -e "s,$depobjname:,$objfile:,g" $depfile >${depsdir}/${objfilebase}.d
        rm -f $depfile
    else
        # "g++ -MMD -o fooobj.o foosrc.cpp" produces fooobj.d


        depfile=`echo "$objfile" | sed -e 's/\..*$/.d/g'`
        if test ! -f $depfile ; then
            # "cxx -MD -o fooobj.o foosrc.cpp" creates fooobj.o.d (Compaq C++)
            depfile="$objfile.d"
        fi



        if test -f $depfile ; then





            sed -e "\,^$objfile,!s,$depobjname:,$objfile:,g" $depfile >${depsdir}/${objfilebase}.d


            rm -f $depfile



        fi
    fi
    exit 0










elif test $DEPSMODE = mwcc ; then
    $* || exit $?
    # Run mwcc again with -MM and redirect into the dep file we want
    # NOTE: We can't use shift here because we need $* to be valid
    prevarg=
    for arg in $* ; do
        if test "$prevarg" = "-o"; then

            objfile=$arg
        else
            case "$arg" in
                -* )
                ;;
                * )
                    srcfile=$arg
                ;;
            esac
        fi
        prevarg="$arg"
    done





    objfilebase=`basename $objfile`
    builddir=`dirname $objfile`

    depsdir=$builddir/$DEPSDIRBASE




    mkdir -p $depsdir




    $* $DEPSFLAG >${depsdir}/${objfilebase}.d

    exit 0


elif test $DEPSMODE = unixcc; then
    $* || exit $?
    # Run compiler again with deps flag and redirect into the dep file.
    # It doesn't work if the '-o FILE' option is used, but without it the
    # dependency file will contain the wrong name for the object. So it is
    # removed from the command line, and the dep file is fixed with sed.
    cmd=""
    while test $# -gt 0; do
        case "$1" in
            -o )
                shift

                objfile=$1
            ;;
            * )
                eval arg$#=\$1
                cmd="$cmd \$arg$#"
            ;;

        esac
        shift
    done


    objfilebase=`basename $objfile`
    builddir=`dirname $objfile`
    depsdir=$builddir/$DEPSDIRBASE
    mkdir -p $depsdir


    eval "$cmd $DEPSFLAG" | sed "s|.*:|$objfile:|" >${depsdir}/${objfilebase}.d
    exit 0


else

    $*
    exit $?





fi



Changes to README-Solaris.txt.

1
2
3
4




5
6
7
8



9




10
11
12
13

14


15
16
17


18
19
20
21
22
23

24
25
26
27
28
29

30

31
32





33



34

35
36
37
For the most part, Solaris is just another Unix variant as far as
MySQL++ is concerned.  See README-Unix.txt for most of what you need
to know to build and use MySQL++.






Prerequisite: Install the MySQL Development Files
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    MySQL++ is built on top of the MySQL C API library, so it needs the



    C API development files to build against.





    With the current version of Solaris, at least, a MySQL package
    is included on the operating system disk, but not installed
    by default.  To install it, oull down the GNOME System menu,

    go to Administration, and then to Package Manager.  Search for


    "mysql5" and install those packages.  While there, you may also
    need to install the gcc packages, if you haven't done that already.
    I'm not sure, but you may need to install Perl as well.



    Don't search for just "mysql" in Package Manager, as that will also
    bring up legacy MySQL 4.0 packages.  MySQL++ may build against 4.0
    still; it's been a while since we've tested it.  What is certain
    is that the examples won't run against 4.0 without modification,
    as they assume the availability of UTF-8 character set support,

    which was added in 4.1.

    It's no doubt possible to use the official binaries from mysql.com
    instead, or to build from source.  We don't do that ourselves,
    though, and don't have reports from those who have, so we can't
    advise on how to do it.




C API Development File Directories





~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~



    Sun's MySQL package installs the development files in relatively

    uncommon locations.  The libraries are in /usr/mysql/lib/mysql,
    and the headers are in /usr/mysql/include/mysql.  Way to be
    redundant, guys. :)
|
|
|

>
>
>
>

|
|
|
>
>
>
|
>
>
>
>

<
<
|
>
|
>
>
|
<
<
>
>

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


22
23
24
25
26
27


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
56
57


/// \file autoflag.h
/// \brief Defines a template for setting a flag within a given variable
/// scope, and resetting it when exiting that scope.

/***********************************************************************
 Copyright (c) 2007 by Educational Technology Resources, Inc.
 Others may also hold copyrights on code in this file.  See the
 CREDITS.txt file in the top directory of the distribution for details.

 This file is part of MySQL++.

 MySQL++ is free software; you can redistribute it and/or modify it
 under the terms of the GNU Lesser General Public License as published
 by the Free Software Foundation; either version 2.1 of the License, or
 (at your option) any later version.

 MySQL++ is distributed in the hope that it will be useful, but WITHOUT
 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
 License for more details.



 You should have received a copy of the GNU Lesser General Public
 License along with MySQL++; if not, write to the Free Software
 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
 USA
***********************************************************************/



#if !defined(MYSQLPP_AUTOFLAG_H)
#define MYSQLPP_AUTOFLAG_H


/// \brief A template for setting a flag on a variable as long as the
/// object that set it is in scope.  Flag resets when object goes
/// out of scope.  Works on anything that looks like bool.

template <class T = bool>
class AutoFlag
{

public:
	/// \brief Constructor: sets ref to true.
	AutoFlag(T& ref) :
	referent_(ref)
	{
		referent_ = true;
	}

	/// \brief Destructor: sets referent passed to ctor to false.
	~AutoFlag()
	{
		referent_ = false;
	}

private:
	T& referent_;
};

#endif // !defined(MYSQLPP_AUTOFLAG_H)



Changes to README-Unix.txt.

1
2

3
4
5

6
7
8
9
10

11
12
13

14

15
16
17
18
19
20
21
22
23
24
25
26
27
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
56
57
58


59

60
61
62
63
64
65


66
67


68
69

70
71
72
73
74
75

76
77
78
79

80
81
82
83
84
85
86
87
88

89


90
91
92
93

94
95
96
97
98
99
100
101
102
103
104

105
106



107
108

109

110
111
Platform Variations
~~~~~~~~~~~~~~~~~~~

    This file only covers details common to all Unix variants
    supported by MySQL++.  For platform-specific details, see the
    file appropriate to your OS:


        README-Cygwin.txt
        README-Linux.txt
        README-Mac-OS-X.txt
        README-Solaris.txt


    There are no special instructions for any other Unix flavors.




Building the Library and Example Programs
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    MySQL++ uses GNU autoconf, so you can build it with the standard
    commands:

    $ ./configure
    $ make
    $ su
    # make install


Configure Options
~~~~~~~~~~~~~~~~~
    The configure script takes several interesting options. Say:


        $ ./configure --help

    to get a list.  Some of the more interesting flags are:

    --prefix:

        If you wish to install mysql++ in a root directory other than
        /usr/local, run configure with --prefix=/some/dir/name


    --with-mysql*:


        If you installed MySQL in an atypical location, the configure
        script will not be able to find the library and header
        files without help.  The simplest way to clue configure into
        where MySQL is installed is with the --with-mysql option.
        Try something like "--with-mysql=/usr/local/mysql", for
        instance.  The configure script will then try to guess which
        subdirectories under the given directory contain the library
        and include files.



        If that doesn't work, it's because the library and header
        files aren't in typical locations under the directory you gave
        for configure to find them.  So, you need to specify them
        separately with --with-mysql-include and --with-mysql-lib
        instead.  As with --with-mysql, configure can often guess
        which subdirectory under the given directory contains the
        needed files, so you don't necessarily have to give the full
        path to these files.
    


    --with-field-limit:


        This lets you increase the maximum field limit for template
        queries and SSQLSes.  By default, both are limited to 25
        fields.  See chapter 8.2 in the user manual for details:

        http://tangentsoft.net/mysql++/doc/html/userman/configuration.html



    --enable-thread-check:



        Builds MySQL++ with threading support, if possible.

        
        This option simply turns on two tests: first, that your
        system uses a compatible threading library; and second,
        that the thread-safe version of the MySQL C API library
        (libmysqlclient_r) is installed and working.  If both of
        these are true, you get a thread-aware version of MySQL++.

        "Thread-aware" means that the library does make an effort to
        prevent problems, but we don't guarantee that all possible
        uses of MySQL++ are thread-safe.


        Note that this is a suggestion, not a command.  If we can't
        figure out the system's threading model or can't find the
        thread-aware build of the C API library, configure won't fail.
        It just reverts to the standard single-thread build.

        See the chapter on threading in the user manual for more
        details and advice on creating thread-safe programs with
        MySQL++.





Building a Static Library
~~~~~~~~~~~~~~~~~~~~~~~~~
    As shipped, MySQL++ only builds a shared library.  It's possible to
    change things so you get a static library instead.


    Before we get to "how," beware that liking statically to MySQL++ has
    legal consequences that may matter to you, due to the library's
    license, the GNU LGPL.  Familiarize yourself with the license, and
    consider getting legal counsel before proceeding.  Also, see the
    MySQL++ FAQ: http://tangentsoft.net/mysql++/#faq  There is more on
    this topic there.

    The necessary changes are all in mysql++.bkl:

        - Change the <dll> tag to <lib>.  (Remember the closing tag!)


        - Remove the <dllname> tag




        - Remove the <so_version> tag



    Then, re-bootstrap the library.  See HACKERS.txt if you need further
    instruction on doing that.
|
<
>
|
|
|
>

<
|
|
|
>

<

>

>
|
<
<
|

|
|
<
<
|
|
<
<
<

>
|

|
|
|

|
|

>
|
>

<
<
|
|
|
|
<
|

>
>
|
<
|
<
<
<
<
<
|
>
>
|
>

<
|
|

|
>
>

<
>
>

<
>
|
<
<
|
|
<
>
|
<
<

>
|
<
<
<

|
<
<

>

>
>
|
<
|
|
>

<
|
<
<
<
<

<

|
>

|
>
>
>

<
>

>
|
|
1

2
3
4
5
6
7

8
9
10
11
12

13
14
15
16
17


18
19
20
21


22
23



24
25
26
27
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
56
57
58
59
60
61

62
63
64

65
66


67
68

69
70


71
72
73



74
75


76
77
78
79
80
81

82
83
84
85

86




87

88
89
90
91
92
93
94
95
96

97
98
99
100
101
MySQL++ was created by Kevin Atkinson during 1998.  From version

1.0 (released in June 1999) through 1.7.9 (May 2001), the primary
maintainer was Sinisa Milivojevic <sinisa@mysql.com>.  Neither Kevin
nor Sinisa are currently involved in MySQL++ development.  The current
maintainer is Warren Young <mysqlpp@etr-usa.com>, starting with
version 1.7.10 in August of 2004.


For a fuller account of the library's history, see the first chapter
of the user manual.  For the nitty-gritty details, see the ChangeLog
in the root package directory.  ChangeLog items since 1.7.9 that
aren't attributed to anyone else were done by Warren Young.



Other contributors of note since 1.7.10:

    Chris Frey <cdfrey@foursquare.net>: Lots of GCC warning fixes
    for the bleeding-edge compiler versions, Gentoo ebuild support,


    and misc other fixes.

    Mark Meredino <Mark_Merendino@cnt.com>: Several fixes and
    additions, including a lot of work on Microsoft Visual C++


    compatibility, and discoveries made while spelunking in the
    library.




    Evan Wies <evan@athenacr.com>: Contributed several C++ code
    style cleanups.

    Arnon Jalon <Arnon.Jalon@247RealMedia.com>: Added the multi-query
    result set handling features, and examples/multiquery.cpp to
    demonstrate it.

    Korolyov Ilya has submitted several patches in many different
    areas of the library.

    Remi Collet <Liste@FamilleCollet.com> is maintaining offical RPMs
    for Fedora, with other systems on the way.  His work has improved
    the RPM spec file we distribute greatly.



    Joel Fielder <joel.fielder@switchplane.com> of Switchplane,
    Ltd. created the ScopedConnection class, came up with the original
    idea for Query's for_each() and store_in() methods, provided the
    basis for examples/for_each.cpp, and provided a fix for exception

    flag propagation in Query.

    Jim Wallace <jwallace@kaneva.com> demonstrated the need
    for BadQuery::errnum(), and contributed the patches and also
    examples/deadlock.cpp to test that this feature does what it is

    supposed to.






    Jonathan Wakely <mysql@kayari.org> rebuilt my original versions
    of ConnectionPool, RefCountedPointer, and RefCountedBuffer.
    They're now simpler and safer.  He also created the numeric
    conversion logic in lib/mystring.h introduced in v3.0.


    Adrian Cornish <mysql@bluedreamer.com>  Several fixes and
    additions.

    Rick Gutleber <rgutleber@above.net> contributed the 
    Query::insertfrom() method and associated InsertPolicy object,
    as well as the SQLStream class.


Here are the personal credits from the old 1.7.9 documentation,
apparently written by Kevin Atkinson:


    Chris Halverson - For helping me get it to compile under Solaris.



    Fredric Fredricson - For a long talk about automatic conversions.


    Michael Widenius - MySQL developer who has been very supportive of
        my efforts.



    Paul J. Lucas - For the original idea of treating the query object
        like a stream.




    Scott Barron - For helping me with the shared libraries.



    Jools Enticknap - For giving me the Template Queries idea.

    M. S. Sriram - For a detailed dission of how the Template Queries
        should be implemented, the suggestion to throw exceptions on bad
        queries, and the idea of having a back-end independent query

        object (ie SQLQuery).

    Sinisa Milivojevic - For becoming the new offical maintainer.


    D. Hawkins and E. Loic for their autoconf + automake contribution.







See the ChangeLog for further credits, and details about the differences
between the many versions of this library.


Please do not email any of these people with general questions about
MySQL++. All of us who are still active in MySQL++ development read the
mailing list, so questions sent there do get to us:


    http://lists.mysql.com/plusplus

The mailing list is superior to private email because the answers are
archived for future questioners to find, and because you are likely to
get answers from more people.

Changes to README-Visual-C++.txt.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

21
22
23
24



25
26
27
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
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
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

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
Prerequisites
~~~~~~~~~~~~~
    You need to have the MySQL C API development files on your system,
    since MySQL++ is built on top of it.

    The easiest way to get it is to download Connector/C from
    mysql.com.

    If you need the MySQL server on your development system anyway,
    you you can choose to install the development files along with
    the server.  Some versions of the MySQL Server installer for
    Windows have installed the development files by default, while
    others have made it an optional install.


Project Files
~~~~~~~~~~~~~
    The distribution comes with three sets of .sln and .vcproj files
    in the vc2003, vc2005 and vc2008 subdirectories.


    We do this for several reasons:

      1. It lets you build MySQL++ with multiple versions of Visual
         C++ without the build products conflicting.




      2. For Visual C++ 2003, we had to disable the SSQLS feature
         because changes made in MySQL++ 3.0 now cause the compiler
         to crash while building.  See the Breakages chapter in the
         user manual for workarounds if you must still use VC++ 2003.



      3. The VC++ 2008 project files get built for 64-bit output, while
         the other two build 32-bit executables.

         With VC++ 2003, we have no choice about this, since it only
         supports 32-bit targets.



         VC++ 2005 did have experimental 64-bit compilers available,
         but their beta nature was only one reason we chose not to
         use them.  The real reason is that the current MySQL++ build
         system isn't currently set up to make it easy to build both
         32- and 64-bit libraries and executables at the same time
         within the same solution.  Bakefile allows it, but it would




         require forking many of the build rules in mysql++.bkl so
         we can do things like have separate MYSQL_WIN_DIR values
         for each bitness.  (See below for more on this variable.)




         For that same reason, the VC++ 2008 project files are set
         up to build 64-bit libraries and executables *only*.

    It is possible to upgrade these project files to work with newer
    versions of Visual C++, but beware that the upgrade feature tends
    to be problematic.

    If you want to do a 32-bit build on VC++ 2008 or newer, it is
    easiest to open the vc2005\* project files and let Visual Studio
    upgrade them for you.  The alternative, starting with the vc2008
    files, requires that you add a 32-bit build option to all of the
    many targets in MySQL++, then optionally delete the 64-bit targets.
    This is a lot more work.  Plus, it only works if you have the
    64-bit compilers installed, since Visual Studio will refuse to
    open project files where all targets must be built with compilers
    that aren't installed, even if your goal is to immediately adjust
    them to use compilers that *are* installed.

    When converting the VC++ 2008 project files to VC++ 2012, Visual
    Studio will change the output directories from Debug to Debug\x64
    (and similar for Release), but it won't also change the link paths
    from Debug to Debug\x64, so that the library and examples will
    compile but not link.  The migration tool detects that there is
    a problem, but it can't fix its own mess.  You have to manually
    fix it.

    There were also problems in VC++ 2010 when you had converted 32-bit
    VC++ 2008 projects and then were trying to switch them to 64-bit.
    It ended up being simpler in this case to just start over from
    scratch and build your own project files.


Using Nonstandard MySQL Installations
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    The Visual Studio project files that come with MySQL++ have
    everything set up correctly for the common case.  The biggest
    assumption in the settings is that you're building against the
    current stable version of Connector/C, which gets installed here
    at the time of this writing:

        C:\Program Files\MySQL\MySQL Connector C 6.1\

    If you installed a different version, or it's in a different
    directory, or you've installed the development files as part of
    MySQL Server on the same machine, you need to change the project
    files to reference the C API development files in that other
    location.  There are two ways to do this.

    The hard way is to make 16 different changes each to 44 separate
    project files.  If you're a talented Visual Studio driver,
    you can do this in as little as about 5 or 6 steps.  You might
    even get it right the first time.  If you are not so talented,
    you have to make all ~700 changes one at a time, and you almost
    certainly will *not* get it right the first time.

    The somewhat easier way is to open all these files in a text
    editor that lets you make a global search and replace on all
    open files.

    The easy way is to install Bakefile (http://bakefile.org/),
    change the value of the MYSQL_WIN_DIR variable near the top of
    mysql++.bkl in the top level of the MySQL++ source tree, and run
    rebake.bat.  This will rebuild all of the project files for you,
    using the new MySQL path in all the many places it's needed.


Building the Library and Example Programs
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    You must build both the Debug and Release versions of the library,
    because a release build of your program won't work with a Debug
    version of the MySQL++ DLL.  These DLLs get different names, so
    you can install them in the same directory if needed: mysqlpp_d.dll
    for the Debug version, and mysqlpp.dll for the Release version.

    With the library built, run at least the resetdb and simple1
    examples to ensure that the library is working correctly.
    In addition to the other generic examples, there are a few
    Visual C++ specific examples that you might want to look at in
    examples\vstudio.  See README-examples.txt for further details.

    Once you're sure the library is working correctly, you can run
    the install.hta file at the project root to install the library
    files and headers in a directory of your choosing.
    


    (Aside: You may not have come across the .hta extension before.
    It's for a rarely-used feature of Microsoft's Internet Explorer,
    called HTML Applications.  Know what Adobe AIR is?  Kinda like
    that, only without the compilation into a single binary blob which
    you must install before you can run it.  Just open install.hta
    in a text editor to see how it works.)


Using MySQL++ in Your Own Projects
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

    This is covered in the user manual, chapter 9.



Working With Bakefile
~~~~~~~~~~~~~~~~~~~~~
    MySQL++'s top-level Visual Studio project files aren't
    maintained directly.  Instead, we use a tool called Bakefile
    (http://bakefile.org/) to generate them from mysql++.bkl. Since

    there are so many project files in MySQL++, it's often simpler to
    edit this source file and "re-bake" the project files from it than
    to make your changes in Visual Studio.

    To do this, download the native Windows version of Bakefile from the
    web site given above.  Install it, and then put the installation
    directory in your Windows PATH.  Then, open up a command window, cd
    into the MySQL++ directory, and type "rebake".  This will run
    rebake.bat, which rebuilds the Visual Studio project files from
    mysql++.bkl.

    There's more information about using Bakefile in HACKERS.txt.



If You Run Into Problems...
~~~~~~~~~~~~~~~~~~~~~~~~~~~
    Especially if you have linking problems, make sure your project
    settings match the above.  Visual C++ is very picky about things
    like run time library settings.  When in doubt, try running one
    of the example programs.  If it works, the problem is likely in
    your project settings, not in MySQL++.

|
<
<
<

<
<
|
<
<
<
<
<
|
|
<
<
<
<

>
|
|
<
|
>
>
>

<
|
<
<
>

>
|
<
|
<
<
>
>

<
<
<
<
<
<
>
>
>
>
<
<
<

>
>
>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<
<
<
|
<
<
<
<
<
<
<
|
<
<
<
<
|
|
<
<
<
<
<
<
|

|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<
<
|
|
<
<
<
<
<
|
|
<
<
<
<
<
<
<
|
<
<
<
<
<
|
<
<
<
|
>
>
|
|
|
|
|
|
|
|
|
<
>
|
|
|
>
|
<
|
|
|
>
<
<
<

<
<
<
<
<
<
|
<
|
|
>
|
<
<
<
<
<
<
|
1



2


3





4
5




6
7
8
9

10
11
12
13
14

15


16
17
18
19

20


21
22
23






24
25
26
27



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
56
57
58
59
60
61
62
63
64
65
66


67
68





69
70







71





72



73
74
75
76
77
78
79
80
81
82
83
84

85
86
87
88
89
90

91
92
93
94



95






96

97
98
99
100






101
<?xml version="1.0" encoding="utf-8"?>






<!-- XSL stylesheet containing additions to the standard DocBook





     chunked-HTML stylesheet.
-->





<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
		version="1.0">
	

	<!-- Import the standard DocBook stylesheet that this one is based on.
	     We use a web URL, but the local XML catalog should resolve this to
			 the local copy of the stylesheet, if it exists. -->
	<xsl:import href="http://docbook.sourceforge.net/release/xsl/current/html/chunk.xsl"/>


	<!-- Bring in local changes common to both HTML and FO output -->


	<xsl:include href="common.xsl"/>

	<!-- The DocBook stylesheets use ISO 8859-1 by default, even when the
	     XML files are marked UTF-8.  If you serve such files from a web

			 server that advertises UTF-8 content, browsers display the page


			 incorrectly, because they believe the web server. -->
	<xsl:output method="html" encoding="UTF-8" indent="no"/>







	<!-- HTML-specific XSL parameters -->
	<xsl:param name="chunk.fast" select="0"/>
	<xsl:param name="html.stylesheet" select="'tangentsoft.css'"/>
	<xsl:param name="use.id.as.filename" select="1"/>




	<!-- Special ulink types, to reduce boilerplate link code -->
	<xsl:template match="ulink" name="refman_ulink">
		<xsl:choose>
			<!-- type=mysqlapi: makes hyperlinks to MySQL C API reference manual,
			     given only the function name with dashes instead of underscores
					 as the URL. -->
			<xsl:when test="@type = 'mysqlapi'">
				<tt>
					<a>
						<xsl:variable name="fn_dash" select="@url"/>
						<xsl:variable name="fn_name"
							select="translate($fn_dash, '-', '_')"/>
						<xsl:attribute name="href">
							<xsl:text>http://dev.mysql.com/doc/mysql/en/</xsl:text>
							<xsl:value-of select="$fn_dash"/>
							<xsl:text>.html</xsl:text>
						</xsl:attribute>



						<xsl:value-of select="$fn_name"/>







						<xsl:text>()</xsl:text>




					</a>
				</tt>






			</xsl:when>

			<!-- type=classref: makes hyperlinks to a class in the MySQL++
			     reference manual, given its name. -->
			<xsl:when test="@type = 'classref'">
				<tt>
					<a>
						<xsl:attribute name="href">
							<xsl:text>../refman/classmysqlpp_1_1</xsl:text>
							<xsl:value-of select="@url"/>
							<xsl:text>.html</xsl:text>
						</xsl:attribute>
						<xsl:choose>
							<xsl:when test="count(child::node())=0">
								<xsl:value-of select="@url"/>
							</xsl:when>
							<xsl:otherwise>


								<xsl:apply-templates/>
							</xsl:otherwise>





						</xsl:choose>
					</a>







				</tt>





			</xsl:when>




			<!-- type=structref: makes hyperlinks to a struct in the MySQL++
			     reference manual, given its name. -->
			<xsl:when test="@type = 'structref'">
				<tt>
					<a>
						<xsl:attribute name="href">
							<xsl:text>../refman/structmysqlpp_1_1</xsl:text>
							<xsl:value-of select="@url"/>
							<xsl:text>.html</xsl:text>
						</xsl:attribute>
						<xsl:choose>

							<xsl:when test="count(child::node())=0">
								<xsl:value-of select="@url"/>
							</xsl:when>
							<xsl:otherwise>
								<xsl:apply-templates/>
							</xsl:otherwise>

						</xsl:choose>
					</a>
				</tt>
			</xsl:when>










			<xsl:otherwise>

				<xsl:call-template name="ulink"/>
			</xsl:otherwise>
		</xsl:choose>
	</xsl:template>






</xsl:stylesheet>

Changes to README-examples.txt.


1

2

3

4
5

6



7

8








































































9

10




11
12

13

14





































































15


















































































16




17








18






19

20



21


22





23





24













































25






26








27







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



56
































































57



58


59




60








































































61

62
63

64


65




66

67

68


































































69

70


71
















































































72




73


74


75

76

77


78


79
































































80

81


82



83


84





85




86




























































87


88



89


90





91


92



93


94




























































95

96


97











98









99




100


















































101





102


103








104



105






























































106


107







108








































































109



110



111




112


113


114


115































































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

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









































Building the Examples

~~~~~~~~~~~~~~~~~~~~~

    If you're installing MySQL++ from the source tarball, the example

    programs get built when you build the library.  If you change
    any example code, just say 'make' to rebuild the examples.

    The examples are built against the headers and library in the



    lib subdirectory, not against the ones you may have installed

    elsewhere on the system.










































































    If these example files were installed on your system as part of




    the -devel RPM, copy all the files to a directory you can write
    to, then say 'make' in that directory.  This uses a simplified

    Makefile, which builds the examples against the headers and

    libraries installed in the system directories.





























































































































































Getting Started with the Examples








~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~






    MySQL++ is built as a shared library on most systems, and a DLL

    on Windows.  Since it isn't built in the same directory as the



    examples, this means that your system won't be able to find the


    library without help until you install it.  Since you generally





    want to run the examples _before_ installing the library, to test





    that the library actually works, we need a workaround.




















































    That workaround is the exrun script.  There are two versions,








    a Bourne shell script called just exrun for POSIX systems, and







    exrun.bat for Windows.





































































    Before running the other examples, you must first create the





    sample database.  On POSIX systems, you do that like so:







        $ ./exrun resetdb [-s server_addr] [-u user] [-p password]






























































    On Windows, that would instead be:







        C:\mysql++\> exrun.bat resetdb [-s server] [-u user] [-p pass]












































































    You don't have to give any of these options.  If you don't pass -s,


    it assumes the database server is running on the same machine,




    and so tries to contact the server over some form of local IPC.

    If you don't pass -u, it uses your own user name when logging







    into to the database server.  If you don't pass -p, it assumes the




    database user has an empty password, which hopefully is not true.



































































    The -s option accepts many different forms of address.  The main








    one is some sort of TCP/IP address, with an optional port number






    or service name.  On Unixy systems, you can give a Unix domain

    socket name.  On Windows, you can give just a period to use named






    pipes, if the server supports it.  All of these are legal:




























































        .
        localhost

        172.20.0.252:12345


        /var/run/mysqld.sock



        my.server.name.com:mysql




































































    If you give -s but don't give a port number or service name with


    it, it assumes the default, port 3306.















































































Running the Other Command Line Examples
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

    The following examples use the database set up by resetdb, and


    have the same command line format as resetdb:






        simple1: Shows the item names for all records in the sample

            stock table.  Try this one if you do nothing else.




































































        simple2: Similar to simple1, but it displays all columns


            from the sample stock table, not just the item name.





















































































        simple3: Same as simple2, except that it retrieves the data


            with a "use" query instead of a "store" query.  See the


            user manual for the difference between these methods.



        ssqls1-5: These demonstrate the SSQLS features.  Read the


            SSQLS sections in the user manual for details about


            these examples.


































































        multiquery: MySQL++ allows you to issue multiple queries at


            once, and get the results as separate sets.  This shows



            that, and also how to use stored procedures, which return


            their results in the same way as a multiquery.










        tquery1-3: Shows how to use the template query facility.































































        transaction: Shows how to use the Transaction class to create



            transaction sets which automatically roll back if not


            explicitly committed.








        deadlock: Shows how to handle errors that happen when the



            database server detects a deadlock in a transaction set.


            Also demonstrates the need for BadQuery::errnum()






























































        store_if: Demonstrates the Query::store_if() method, which


            allows you to store the results of a query in an STL











            container conditionally.  Think of it as a way to express









            rules for selecting records in C++, to be used when SQL's




            WHERE clause isn't powerful enough.
























































        for_each: Demonstrates the Query::for_each() method, which


            allows you to execute a query and call a functor on each








            returned row.  This example uses this to gather statistics



            on the sample table's contents.

































































        cpoolp, cpoolw: Respectively, the POSIX and Windows threads







            variants of the ConnectionPool class demonstration.












































































        load_jpeg: Inserts a JPEG file into the sample database,



            for use by the cgi_jpeg example.  (See below.)  Unlike the




            other examples, this one takes anything given on the


            command line that isn't a switch to be a JPEG file name.


            We've included examples/logo.jpg as a sample, if you want


            to use that.




































































        fieldinf: Shows how to get information about the fields in


            a result set.  (Types, etc.)












        dbinfo: Dumps a bunch of information about the database




            server and some of the data it's managing.





























































    If you run the load_jpeg example, you should consider also


    playing with the other half of the demonstration, cgi_jpeg.


    To run it, you'll need to install MySQL++ on a machine with

    a web server, then copy the cgi_jpeg program to the server's


    CGI directory.  For example, on a stock Red Hat type box,



    that would be /var/www/cgi-bin.  At that point, a request like

    http://my.server.com/cgi-bin/cgi_jpeg?id=1 should show the JPEG you
    loaded.  The ID value to use will be that reported by load_jpeg.


















































































Dedicated Windows Examples
~~~~~~~~~~~~~~~~~~~~~~~~~~


    If you're a Visual C++ user, there are two GUI examples, too:





































































        examples\vstudio\mfc.vcproj: MFC-based replacement for
            the simple2 example.













































































        examples\vstudio\wforms.vcproj: The same thing, only written in

            C++/CLI and using Windows Forms.  Please follow the

            instructions in README-Visual-C++.txt before trying to
            build and run this example.  The MySQL++ library build

            settings must be modified and the library rebuilt first.
















































































    Although these examples show use of MySQL++ in a GUI rather than



    command line program, that's not the main point of these examples.




    What we're really showing here is how to deal with Unicode.


    The MySQL server prefers the UTF-8 encoding for Unicode, which


    works naturally with most non-Windows systems.  Windows, on the
    other hand, uses a different Unicode character encoding, UCS-2.

    These examples show how to do the necessary conversions.  (See the



    Unicode chapter in the user manual for more on this topic.)



































































    We need two different examples because Unicode conversions and






    string handling are so wildly different under .NET than with the

    native Win32 API.  .NET makes these tasks much easier.



































































    These examples build and run as-is under Visual C++ 2005.  To make


    them work with VC++ 2008, you will have to change several paths


    in both project's settings to reference the "vc2008" subdirectory

    instead of "vc2005":











































































        o Configuration Properties > Debugging > Working Directory























        o Configuration Properties > Linker > General >












          Additional Library Directories















































    If you want to backport these examples to VC++ 2003, it's probably
















































    not hard.  The main difficulty is that VS 2003 supports Managed

    C++, which isn't the same thing as C++/CLI.







































Special exrun Capabilities

~~~~~~~~~~~~~~~~~~~~~~~~~~









    The Bourne shell version of the exrun script has a few features

    not avaiable in the Windows batch file version.  These features











    let you run the examples under various debugging tools.





















































    You can get simple gdb debugging if you run an example like this:










        $ ./exrun gdb simple1 foo bar qux



















    The script also supports valgrind, in memory leak testing mode:









        $ ./exrun valgrind simple1 foo bar qux








































>
|
>
|
>
|
>
|
|
>
|
>
>
>
|
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

>
|
>
>
>
>
|
|
>
|
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

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

>
>
>
>
|
>
>
>
>
>
>
>
>
|
>
>
>
>
>
>
|
>
|
>
>
>
|
>
>
|
>
>
>
>
>
|
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
|
>
>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

>
>
>
>
>
|
>
>
>
>
>
|
>
>

>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

>
|
>
>
>
>

>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

>
>
>
|
>
>
|
>
>
>
>
|
>
|
>
>
>
>
>
>
>
|
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

>
>
>
|
>
>
>
>
>
>
>
>
|
>
>
>
>
>
>
|
>
|
>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

>
>
>
|
|
>
|
>
>
|
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

>
>
>
|
>
>
|
>
>
>
>

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

>
|
|
>
|
>
>
|
>
>
>
>

>
|
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

>
|
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

>
>
>
>
|
>
>
|
>
>
|
>

>
|
>
>
|
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

>
|
>
>
|
>
>
>
|
>
>
|
>
>
>
>
>

>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

>
>
|
>
>
>
|
>
>
|
>
>
>
>
>

>
>
|
>
>
>
|
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

>
|
>
>
|
>
>
>
>
>
>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
|
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

>
>
>
>
>
|
>
>
|
>
>
>
>
>
>
>
>
|
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

>
>
|
>
>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

>
>
>
|
>
>
>
|
>
>
>
>
|
>
>
|
>
>
|
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

>
>
>
>
|
>
>
|
>
>
>

>
>
>
>
>
>
>
>
|
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

>
>
|
>
>
|
>
>
|
>
|
>
>
|
>
>
>
|
>
|
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

>

>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
|
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

>
>
>
>
>
>
|
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

>
|
>
|
>
|
|
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

>
>
>
|
>
>
>
|
>
>
>
>
|
>
>
|
>
>
|
|
>
|
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
>
>
>
>
>
>
|
>
>
>
>
>
>
|
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

>
>
|
>
>
|
>
>
|
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

>
|

>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

>

>
>
>
>
>
>
|
>
|
>
>
>
>
>
>
>
>
>
|
>
|
>
>
>
>
>
>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

>
|
>
>
>
>
>
>
>
>

>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

>
|
>
>
>
>
>
>
>

>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
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
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
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
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
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
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
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
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
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
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
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
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
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
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
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
1694
1695
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
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
1883
1884
1885
1886
1887
1888
1889
1890
1891
1892
1893
1894
1895
1896
1897
1898
1899
1900
1901
1902
1903
1904
1905
1906
1907
1908
1909
1910
1911
1912
1913
1914
1915
1916
1917
1918
1919
1920
1921
1922
1923
1924
1925
1926
1927
1928
1929
1930
1931
1932
1933
1934
1935
1936
1937
1938
1939
1940
1941
1942
1943
1944
1945
1946
1947
1948
1949
1950
1951
1952
1953
1954
1955
1956
1957
1958
1959
1960
1961
1962
1963
1964
1965
1966
1967
1968
1969
1970
1971
1972
1973
1974
1975
1976
1977
1978
1979
1980
1981
1982
1983
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993
1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
2027
2028
2029
2030
2031
2032
2033
2034
2035
2036
2037
2038
2039
2040
2041
2042
2043
2044
2045
2046
2047
2048
2049
2050
2051
2052
2053
2054
2055
2056
2057
2058
2059
2060
2061
2062
2063
2064
2065
2066
2067
2068
2069
2070
2071
2072
2073
2074
2075
2076
2077
2078
2079
2080
2081
2082
2083
2084
2085
2086
2087
2088
2089
2090
2091
2092
2093
2094
2095
2096
2097
2098
2099
2100
2101
2102
2103
2104
2105
2106
2107
2108
2109
2110
2111
2112
2113
2114
2115
2116
2117
2118
2119
2120
2121
2122
2123
2124
2125
2126
2127
2128
2129
2130
2131
2132
2133
2134
2135
2136
2137
2138
2139
2140
2141
2142
2143
2144
2145
2146
2147
2148
2149
2150
2151
2152
2153
2154
2155
2156
2157
2158
2159
2160
2161
2162
2163
2164
2165
2166
2167
2168
2169
2170
2171
2172
2173
2174
2175
2176
2177
2178
2179
2180
2181
2182
2183
2184
2185
2186
2187
2188
2189
2190
2191
2192
2193
2194
2195
2196
2197
2198
2199
2200
2201
2202
2203
2204
2205
2206
2207
2208
2209
2210
2211
2212
2213
2214
2215
2216
2217
2218
2219
2220
2221
2222
2223
2224
2225
2226
2227
2228
2229
2230
2231
2232
2233
2234
2235
2236
2237
2238
2239
2240
2241
2242
2243
2244
2245
2246
2247
2248
2249
2250
2251
2252
2253
2254
2255
2256
2257
2258
2259
2260
2261
2262
2263
2264
2265
2266
2267
2268
2269
2270
2271
2272
2273
2274
2275
2276
2277
2278
2279
2280
2281
2282
2283
2284
2285
2286
2287
2288
2289
2290
2291
2292
2293
2294
2295
2296
2297
2298
2299
2300
2301
2302
2303
2304
2305
2306
2307
2308
2309
2310
2311
2312
2313
2314
2315
2316
2317
2318
2319
2320
2321
2322
2323
2324
2325
2326
2327
2328
2329
2330
2331
2332
2333
2334
2335
2336
2337
2338
2339
2340
2341
2342
2343
2344
2345
2346
2347
2348
2349
2350
2351
2352
2353
2354
2355
2356
2357
2358
2359
2360
2361
2362
2363
2364
2365
2366
2367
2368
2369
2370
2371
2372
2373
2374
2375
2376
2377
2378
2379
2380
2381
2382
2383
2384
2385
2386
2387
2388
2389
2390
2391
2392
2393
2394
2395
2396
2397
2398
2399
2400
2401
2402
2403
2404
2405
2406
2407
2408
2409
2410
2411
2412
2413
2414
2415
2416
2417
2418
2419
2420
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
2475
2476
2477
2478
2479
2480
2481
2482
2483
2484
2485
2486
2487
2488
2489
2490
2491
2492
2493
2494
2495
2496
2497
2498
2499
2500
2501
2502
2503
2504
2505
2506
2507
2508
2509
2510
2511
2512
2513
2514
2515
2516
2517
2518
2519
2520
2521
2522
2523
2524
2525
2526
2527
2528
2529
2530
2531
2532
2533
2534
2535
2536
2537
2538
2539
2540
2541
2542
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
2587
2588
2589
2590
2591
2592
2593
2594
2595
2596
2597
2598
2599
2600
2601
2602
2603
2604
2605
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
2657
2658
2659
2660
2661
2662
2663
2664
2665
2666
2667
2668
2669
2670
2671
2672
2673
2674
2675
2676
2677
2678
2679
2680
2681
2682
2683
2684
2685
2686
2687
2688
2689
2690
2691
2692
2693
2694
2695
2696
2697
2698
2699
2700
2701
2702
2703
2704
2705
2706
2707
2708
2709
2710
2711
2712
2713
2714
2715
2716
2717
2718
2719
3.0.6, 2008.08.16 (r2350)

    o Several fixes to allow thread-aware build on Solaris

    o More improvements to search for Fink version of C API library.

    o Various improvements to Windows installer (install.hta)


3.0.5, 2008.08.06 (r2332)

    o Replaced install.bat with new install.hta, which has a GUI and a
      lot of embeded logic for doing The Right Thing, which we couldn't
      do in a dumb batch file.

    o Several fixes to allow it to build on Solaris 10.

    o Fixed a bug in comparison of Null<T> to T: wouldn't always give
      the right result for one particular combination of argument
      values and order of parameters to operator <().  It wouldn't
      fail all the time, either; it depended on the way the system's
      memory allocator dealt with newly allocated RAM.  The bug was
      discovered during the Solaris 10 porting effort, but it is not
      a Solaris-specific bug.

    o Split Linux-specific material out of README-Unix.txt into
      README-Linux.txt, and created README-Solaris.txt.

    o Shipping a vc2008 directory.  Populated by bootstrap script with
      copies of vc2005 files when those are newer, with the idea being
      to update them by hand by running them through VC++2008 before
      release.

    o Several fixes to VS-only examples. They hadn't been updated to
      track several of the changes in MySQL++ v3, so they wouldn't
      build OOTB at all, crashed when you did get them building, and
      emitted a lot of warnings during the build.  Cleaned it all up.

    o Autoconf now explicitly checks whether we need to link to zlib
      to link to MySQL C API library.  It used to be required, but
      lately, MySQL has been shipping the library with zlib stuff
      embedded, causing multiply defined symbol errors on some systems.

    o configure script now looks in more locations for the MySQL C API
      library, adding default locations for Fink and Solaris.


3.0.4, 2008.07.02 (r2303)

    o Fixed a few bugs in SslOption that prevented it from actually
      working.  If you've been having SSL problems since upgrading
      to MySQL++ v3, this is why!  Thanks for these patches go to
      Petteri Kiiskinen.

    o Changed type of String's internal "size" typedefs so it'll
      build without errors on 64-bit systems where these ints are
      different sizes.

    o Many user manual improvements.


3.0.3, 2008.05.11 (r2284)

    o Fixed query well-formedness handling in Query::store() and use().
      It was quietly eating these errors, confusing them with the
      no-results case.

    o Fixed examples/cpool.cpp to build without thread support.

    o No longer hiding all stdint.h typedefs inside namespace mysqlpp.

    o Fixed mysqlpp::String comparisons of empty strings against
      nonempty strings; if the empty string was on the left hand side,
      it would succeed because it was only comparing against characters
      in the empty side, which matches everything.  (Fixes bug 11588.)


3.0.2, 2008.04.13 (r2275)

    o Increased float to string conversion precision from 7 to 9 and
      double from 16 to 17 digits.  Previous values weren't enough
      near the maximum values that each can hold.

    o Replaced Query's safe bool mechanism with an override of
      basic_ios::operator void*() to avoid a conflict between the
      two mechanisms.  As the base class version isn't virtual,
      this is arguably evil, but it should be harmless in typical use.
      Besides, testing Query in bool context usually isn't the right
      thing anyway: test the result set instead.

    o Made ConnectionPool::grab() virtual.

    o Overriding ConnectionPool::grab() and release() in
      examples/cpool.cpp to show how to do connection-in-use count
      limiting.  Also, added a few more output indicator states to
      allow one to better understand program flow.


3.0.1, 2008.03.23 (r2263)

    o String objects can now be compared to mysqlpp::null directly.

    o Added a template operator== and operator!= to String, syntactic
      sugar for the existing String::compare() methods.

    o String::compare() now returns 0 ("equal") when one of the
      strings is an uninitialized String() (no refcounted buffer)
      and the other is empty.  It used to consider any initialized
      string greater than an uninitted one.  An uninitialized String
      appears empty, though, so this was incorrect.

    o Made Connection::thread_aware(), thread_start() and thread_end()
      static methods, so they can be called before you create your
      first connection.  Ditto for DBDriver versions of these methods.

    o Calling Connection::thread_start() and thread_end() in
      examples/cpool.cpp, as appropriate.  Above changes were necessary
      to make this work sensibly.

    o Made ConnectionPool::release() virtual, so your pool subclass can
      override it.

    o Added ConnectionPool::size(), so a subclass can know the current
      number of extant connections.

    o No longer single-quoting NOW() call generated for default
      init of DateTime type when building queries from SSQLS objects
      in Query::insert(), replace() and update().  The template query
      and stream interfaces of Query treated NOW() correctly already.

    o Fixed a bug that left SSQLS::table_override_ uninitted if
      you used certain of the generated ctors or set() member
      functions instead of others used by the examples.  This could
      cause a crash any time you caused SSQLS.table() to be called,
      such as when passing the SSQLS to Query::insert().

    o Minor memset bug fixed in test/uds.cpp.  Patch by Dave Jones.


3.0.0, 2008.02.29 (r2236) The "Giant Leap Forward" release

    THIS IS NOT A DROP-IN REPLACEMENT FOR MySQL++ v2.x!

    You will have to recompile your program against this version
    of the library, and you will almost certainly have to make code
    changes as well.  Please see these sections in the user manual
    for information on migrating your code to this new version:

    http://tangentsoft.net/mysql++/doc/html/userman/breakages.html#api-3.0.0
    http://tangentsoft.net/mysql++/doc/html/userman/breakages.html#abi-3.0.0

    o Added ConnectionPool class, primarily to let multithreaded
      programs share a set of Connection objects safely in situations
      where it isn't acceptable to have a Connection per thread.

    o Created examples/cpool.cpp to demonstrate this new class.

    o Added RefCountedPointer template, which provides automatic
      memory management and data sharing.  It's not intended
      for use outside of MySQL++ itself, but it's the mechanism
      behind everything below where reference counting is mentioned.
      I created the initial version of it, but Jonathan Wakely almost
      completely rebuilt it, and Joseph Artsimovich provided helpful
      commentary and advice as well.

    o Many improvements to Specialized SQL Structures (SSQLS):

      - Renamed custom* to ssqls*.  There's still a custom.h which
        #includes ssqls.h for you, but it's only intended to ease
        the transition to the new name.  It will go away in a future
        release, probably as soon as v3.1.

      - SSQLSes are finally compatible with Null<>-wrapped types.  This
        feature is based loosely on the "Waba" patch posted to the
        mailing list back in the v2.0 days, but extended to allow
        Null<T> types for key fields.  (The Waba patch only allowed
        these types in non-key fields.)

      - It's no longer necessary to define a different SSQLS for each
        different field set you use in queries.  That is to say,
        you can define an SSQLS for an entire table and store just a
        subset of the table in it now, with the other fields keeping
        default values.  Removed examples/custom6.cpp, as custom1.cpp
        can now demonstrate the same thing, implicitly.

      - An SSQLS's field order no longer has to match the order of
        fields in the result set it is populated from.

      - As a result of previous, removed sql_create_c_order_* macros;
        they have no purpose now.

      - Removed order parameters from sql_create_complete_*, which now
        gives it the same functionality as sql_create_c_names_* so
        removed the latter, too.

      - Removed "basic" variants of SSQLS creation macros.  They've
        been unofficially deprecated by dint of being all but
        undocumented and unexemplified for a very long time now.

      - It's now possible to use mysqlpp::String, Date, DateTime, and
        Time types in the key field positions in an SSQLS as they
        now support the necessary comparison interfaces.

      - If you use a floating-point data type in one of the key field
        positions, it no longer uses exact comparison logic.  Instead,
        it now does [in]equality comparisons by testing whether the
        difference between two floating-point values is less than a
        configurable threshold defaulting to 0.00001.
    
      - You can now use 'bool' type in an SSQLS.

      - Renamed _table static member variable in each SSQLS to table_
        and made it private.  There are now public setter and getter
        methods, table().

      - Added per-instance table name overriding via instance_table()
        setter.  table() getter returns static version if this is not
        set, so it's still a global setting by default.

    o You can now use mysqlpp::null as a template query parameter to
      get a SQL null.

    o Replaced template ColData_Tmpl<T>:

      - Used to have typedef ColData_Tmpl<std::string> MutableColData.
        It was used only once within MySQL++ itself, and was never
        documented as a class for end users.  This one use within
        the library was a crock, so we just replaced this use with
        std::string and removed the typedef.

      - This left just one use of ColData_Tmpl<T>, instantiating it
        with the MySQL++ utility class const_string, basically a
        clone of std::string with all the mutating features removed.
        Folded the functionality of const_string into the template,
        renamed the result to String, and deleted the const_string
        class.  It'd be a complete std::string replacement -- with
        SQL-related enhancements -- if it were modifiable, but MySQL++
        doesn't need it to be modifiable.  Yet, it's still the closest
        thing MySQL++ has to its own string type; thus the name.

      - Replaced its internal buffer management with a much more
        clever reference counted scheme.  This shows its greatest
        advantage in the return from Row::operator[](), which for
        technical reasons must return by value, not by reference
        as is more common.  This lets you pass around Strings by
        value while having the efficiency of reference semantics.
        This can be important with large return values, like BLOBs.

      - Converting String to numeric types (ints, floats...) uses a
        new, cleaner system by Jonathan Wakely.  Unless you were
        abusing weaknesses in the old system, you won't see a
        difference.  It's just more robust and flexible.

    o Redesigned SQLString:

      - It used to derive from std::string, and while MySQL++'s
        internals did use it in place of std::string, these places
        didn't take advantage of the additional features offered
        by SQLString.  So, replaced all those uses with std::string.

      - All the remaining uses are MySQL++ public interfaces that
        need to be able to accept any of many different data types,
        and we want that data to be automatically converted to a
        SQL-compatible string form.  Because it no longer has the
        parentage to be a general-purpose string type and MySQL++ has
        a new contender for that role (String), renamed SQLString to
        SQLTypeAdapter to reflect its new, limited purpose.  ("STA"
        for short.)

      - Since we don't have the std::string base class to manage the
        string buffer any more, using the same reference counted
        buffer mechanism as String.  In addition to saving code by
        not creating yet another buffer management mechanism, it means
        objects of the two classes can share a buffer when you assign
        one to the other or pass one to the other's copy ctor.

      - Added many more conversion ctors.

      - STA interfaces using the 'char' data type now treat them as
        single-character strings instead of one-byte integers, as
        does the Standard C++ Library.

      - Added mysqlpp::tiny_int interfaces to STA to replace the
        former char interfaces for those needing one-byte integers.

    o As a result of the ColData -> String redesign, removed
      Row::raw_*().  Before String copies were efficient, this
      was helpful in accessing BLOB data efficiently.  It was also
      required back when ColData didn't deal correctly with embedded
      null characters, but that reason is gone now, too.

    o Row::operator[](const char*) no longer unconditionally throws the
      BadFieldName exception when you ask for a field that doesn't
      exist.  It will still throw it if exceptions are enabled, but if
      not, it'll just return an empty String.  This was necessary to
      make the SSQLS subset and field order independence features work.

    o Similarly, Result::field_num() returns -1 when exceptions are
      disabled and you ask for a field that doesn't exist.

    o You can now use the OptionalExceptions mechanism to disable
      exceptions on const MySQL++ objects.

    o Redesigned query result classes:

      - Instead of Result deriving from ResUse, the two derive from
        a common base class -- ResultBase -- containing the bits that
        are truly the same between them.  Before, Result inherited
        several methods that didn't really make sense for "store"
        query result sets.

      - Renamed Result to StoreQueryResult and ResUse to UseQueryResult
        so it's clearer what each is for.

      - Renamed ResNSel to SimpleResult.

      - Made all SimpleResult data members private and hid them behind
        const accessor functions of the same name.

      - The result set classes all used to be friends of Connection
        for various lame reasons.  Since they are created by Query,
        and Query has a good reason for a strong relationship with
        Connection, moved Connection access out of each result set
        class into the code in Query that creates that type of result
        set object.

      - StoreQueryResult now derives from vector<Row> in addition to
        ResultBase; it used to merely emulate a vector of Rows, poorly.
        It can now dispose of the MYSQL_RESULT at the end of object
        construction, because it creates all the Row objects up front
        instead of on the fly.  And as a result of *that*, operator[]
        returns by reference instead of by value, operator -> works
        correctly on iterators, all STL algorithms work, etc., etc.

      - IMPORTANT COMPATIBILITY BREAK: because we used fetch_row()
        stuff in Result previously, it was okay to index past the
        end of the result set: you'd just get a falsy Row when you
        did this, just as happens when doing the same thing in a
        "use" query.  The simple1 and simple2 examples did this,
        so it's likely that code exists that takes advantage of this
        misfeature.  New versions of these examples show how to index
        through a StoreQueryResult without running past its end.

      - ResUse used to delay creation of its FieldNames and FieldTypes
        objects until the point of need.  This had several implications
        for thread and exception safety that we fix by just creating
        them in the ctor.  If your code is multi-threaded and was
        avoiding certain usage patterns due to crashes, it's worth
        trying your preferred way again.

      - Result sets create a few data structures to hold information
        common to all rows in that set.  The row objects need access
        to these shared data structures, so on creation each gets
        a pointer back to the result set object that creates it.
        This was efficient, but required that a result set object
        outlive any row objects it creates.  Now these shared data
        structures are reference-counted, decoupling the lifetime of
        the child row objects from their result set parent.

      - Copy operations for result sets used to actually be "moves"
        before, for efficiency.  (MySQL++ itelf only copied result
        sets in returning them by value from the query execution
        methods of Query, so this was acceptable if you didn't do
        anything uncommon with these objects.)  Reference counted
        data structures allow us to have copy semantics now without
        sacrificing efficiency.

      - You can now use Query::storein() with an STL container of Row
        objects now, instead of having to use SSQLSes.  The lifetime
        issue guaranteed a crash if you tried this before.

      - Removed a bunch of unnecessary alias methods:

        - columns() -> num_fields()
        - names()   -> field_names()
        - rows()    -> num_rows()
        - types()   -> field_types()

      - Renamed several methods for grammar reasons:

        - fields(unsigned int)      -> field(unsigned int)
        - names(const std::string&) -> field_num(const std::string&)
        - names(int)                -> field_name(int)
        - types(int)                -> field_type(int)

      - Removed several "smelly" methods:

        - purge()
        - raw_result()
        - reset_names()
        - reset_field_names()
        - reset_types()
        - reset_field_types()

    o Field class used to just be a typedef for the corresponding C
      API class.  Now it's a real C++ class providing a more MySQL++
      sort of interface, plus good OO things like information hiding
      and implementation detail abstraction.  This changes several
      things about the interface.

    o Fields class was basically a specialized std::vector work-alike
      for dealing with the C API to get access to MYSQL_FIELD objects
      and present them as contained Field objects.  New Field type
      let us replace it with "typedef std::vector<Field> Fields"

    o Major improvements to the quoting and escaping mechanisms:

      - Replaced almost all of the type-specific interfaces in manip.h
        with a single version taking STA.  The compiler can convert
        almost anything to STA without losing any information we need
        for correct quoting and escaping.  This has the side benefit
        that we can now do correct quoting and escaping for more data
        types now, including plain C and C++ string types.

      - Fixed a bug in quote_double_only manipulator for String: was
        using single quotes by mistake.

      - Escaping and quoting only works in instances where MySQL++
        can tell you're building a SQL query and are using a data type
        that requires it.  This affects many things, but the one most
        likely to cause trouble is that inserting MySQL++'s quoting
        and escaping manipulators in non-Query ostreams is now a no-op.

      - Added escape_string() member functions to Query and
        SQLQueryParms::escape_string(), and removed the global function
        of the same name.  Because these are tied indirectly to a
        Connection object, this also has the effect that escaping is
        now aware of the current default character set used by the
        database server.  There's only one case where this isn't done
        now, and that's when we're disconnected from the server.

      - Previous two items form a trade-off: if your code was depending
        on MySQL++ to get SQL escaping and it no longer happens for
        what we consider a good reason, you can build a replacement
        mechanism using these new functions.  Quoting needs no special
        support in MySQL++.

      - Removed 'r' and 'R' template query parameter modifiers,
        which meant "always quote" and "always quote and escape"
        regardless of the data type of the parameter.  There are no
        corresponding manipulators (for good reason), so the removal
        restores symmetry.

    o Created DBDriver class from code previously in Connection and
      Query to almost completely wrap the low-level MySQL C API:

      - Connection creates a DBDriver object upon connection and
        passes a pointer to it down to Query objects it creates.
        In turn, they pass the pointer on to any of their children
        that need access to the C API.

      - Nothing outside DBDriver calls the C API directly now, though
        DBDriver leaks C API data structures quite a lot, so this
        feature doesn't constitute "database independence."  See the
        Wishlist for what must be done to get to that point.

    o Completely redesigned the connection option setting mechanism:

      - There's now just a single Connection::set_option() method that
        takes a pointer to the abstract Option base class, and there is
        an Option subclass for every connection option we understand.
        Thus, type errors are now caught at compile time instead of
        at run time.

      - Replaced Connection::enable_ssl() with SslOption class.

      - Enabling data compression and setting the connection timeout
        are no longer set via parameters to Connection interfaces.
        These are now set with CompressOption and ConnectTimeoutOption.

      - Similarly, removed client_flag parameters from Connection's
        ctor and connect() method and added corresponding Option
        subclasses.  There's about a dozen, so rather than list them
        here, look for similarly-named classes in lib/options.h.

    o Added Connection::count_rows() to execute "SELECT COUNT(*) FROM
      tablename" queries for you.

    o Moved Connection::affected_rows(), info() and insert_id() methods
      to class Query, as they relate to the most recently-executed
      query, not to the connection.

    o Several method name changes in Connection:

      - client_info()   -> client_version()
      - host_info()     -> ipc_info()
      - proto_info()    -> protocol_version()
      - server_info()   -> server_version()
      - stat()          -> status()

    o Removed Connection::api_version().  It does the same thing as
      client_version().

    o Lots of changes to Date, DateTime, and Time classes:

      - If you use the default constructor for DateTime and don't
        subsequently set its year, month, day, hour, minute or second
        data members to nonzero values, it becomes the SQL function
        "NOW()" in a query string.  You can also use DateTime::now()
        as syntactic sugar for this.

      - As a result of above, had to hide all of DateTime's data
        members behind accessor functions, to keep the state of the
        object consistent.  (If it's initialized as "now" and you
        give it an explicit year value, say, it is no longer "now",
        so the setter has to clear the now-flag.)  There are getters
        and setters for year, month, day, hour, minute and second,
        all named after the member.

      - Did the same for Date and Time for consistency, even though it
        isn't technically required.

      - The sql_timestamp typedef now aliases DateTime instead of Time.

      - Renamed template class DTbase<T> to Comparable<T>.  The fact
        that it's the common base class of all date and time classes
        is irrelevant; making subclasses comparable is what it does,
        so that's what it should be named after.

      - Added a DateTime ctor taking discrete year, month, day, hour,
        minute, and second values.

      - Implicit conversion from stringish types to the date and time
        types is no longer allowed.  This is part of the "Waba"
        Null<T> patch mentioned above; allowing implicit conversions
        would break this new feature.

      - Added operator std::string and str() methods to all of these
        classes.  Adding this to the existing operator << support, you
        now have several ways to convert these objects to string form.

      - Added time_t conversion to Date and Time classes.  DateTime
        already had it, since it's more legitimate to convert time_t
        to DateTime, but you could already "slice" it with something
        like Time(DateTime(time(0))) so there's no point pretending
        you can't get from time_t to Date or Time.  Might as well
        legitimize it.

    o Improved tiny_int class:
        
      - Turned it into a template parameterized on the value type so
        you can get both signed and unsigned TINYINTs

      - Changed the sql_tinyint and sql_tinyint_unsigned typedefs to
        use mysqlpp::tiny_int<VT> instead of raw chars

      - Added a bool conversion ctor and operator, and typedef'd it
        to sql_bool and sql_boolean to match MySQL server behavior

    o Added many more sql_* typedefs.  We now have a typedef for every
      type the MySQL server knows about, including those it supports
      just for compatibility with other database servers.

    o Changed the sql_*int* typedefs to use integer types of the same
      size as the MySQL server.  (Run test/inttypes.cpp to test it.)

    o Added copy ctor and assignment operator to Row.

    o Row::operator[]() takes int now instead of unsigned int.
      This finally (!) makes it possible to say row[0] without the
      compiler giving an ambiguous overload error.

    o Changed all uses of row.at(0) in the examples to row[0]

    o Added operator[] to all classes that only had at().

    o Query now automatically resets itself unless the query fails
      or you're using template queries.  In either case, the contents
      of the query's internal buffers are considered precious,
      either for debugging, or future queries.  Except when using
      template queries, this means you may be able to avoid calling
      Query::reset() entirely.  It's still safe to call reset()
      as before, just unnecessary most of the time.

    o Removed reset_query parameter from all Query methods.  It was
      almost completely broken before, and above change does what
      was really wanted to begin with.

    o Query::store_next() and Result::fetch_row() no longer throw
      the EndOfResults and EndOfResultSets exceptions; these are not
      exceptional conditions!  These methods simply return false now.

    o Removed examples/usequery.cpp: there's no essential difference
      between what it did and what examples/simple3.cpp does now as
      a result of the previous change.

    o Added Query::exec(void), paralleling Query::execute(void).

    o Removed Query::preview().  The most direct replacement is str(),
      which has always done the same thing.

    o You can now insert a Query object into an ostream to get a copy
      of the built query.  This means Query::str() is only necessary
      when using template queries.

    o Removed overloads of Query::execute(), store(), and use()
      that take const char*.  It was redundant because const char*
      converts implicitly to STA, for which overloads already exist.

    o Renamed Query::def to Query::template_defaults to make its
      purpose clearer.

    o Query::error() now returns const char*, not a std::string by
      value.  There's no point in making a copy of the error string.
      The method is now const as well, as it doesn't change the
      Query object.

    o Added Query::errnum(), which just wraps Connection::errnum().

    o Added error number parameters and accessor functions to BadQuery,
      ConnectionFailed and DBSelectionFailed exceptions, to preserve
      the state of Connection::errnum() at the point of the exception,
      so you don't have to rely on this value remaining unchanged
      during the exception throw process.  All places that use these
      exceptions now include this value where possible.  Thanks for the
      initial patch go to Jim Wallace.

    o Removed Lockable mechanism from Connection and Query; it was
      conceptually flawed.  See the new user manual chapter on
      threading for advice on using MySQL++ safely without locking.
      There is mutex locking now in ConnectionPool, but that's it.

    o Connection::query() now takes an optional query string, allowing
      the returned Query object to start off with a value.  Especially
      useful when the query string is static, either because it's
      a simple query or because it's a template.  You can now build
      chains like "if (conn.query("CREATE INDEX ...").exec()) { ..."

    o Added Connection::thread_aware(), thread_end(), thread_id()
      and thread_safe().  See user manual's threading chapter for
      explanations.

    o Renamed "success" data members in Connection, Query and
      SimpleResult (neé ResNSel) to "copacetic_", making them private
      if they weren't before.  This better reflects their actual
      use, which isn't to say that there has necessarily been actual
      success, but rather that everything's okay with the object.

    o Removed success() member functions from above classes.  All can
      be tested in bool context to get the same information.

    o Replaced all operator bool()s in MySQL++ classes with safer
      alternatives.  See http://www.artima.com/cppsource/safebool.html
      Thanks to Jonathan Wakely for much helpful commentary, advice,
      and code used in these mechanisms.

    o Decoupled Connection::copacetic_ from Connection::is_connected_.
      It is now possible for the object to be copacetic without being
      connected.  However, if it tries to connect and fails, then
      it is not copacetic.  If it is copacetic and not connected, it
      means we haven't even tried to connect yet, a useful distinction.

    o Collapsed Connection's host, port, and socket_name down into
      a new combined 'server' parameter which is parsed to determine
      what kind of connection you mean.  These interfaces are still
      compatible with v2.3 and earlier up through the port parameter.
      There are differences beyond this.

    o Added TCPConnection, UnixDomainSocketConnection and
      WindowsNamedPipeConnection subclasses for Connection giving
      simpler construction and connect() method interfaces for
      instances where you know what kind of connection you want at
      compile time.

    o Changed Connection::ping() return value from int to bool.

    o Renamed NullisNull to NullIsNull -- capital I -- and similar for
      NullisZero and NullisBlank.

    o It's now a compile-time error to try to convert a MySQL++
      representation of a SQL null to any other data type, rather
      than a run-time error as in previous versions.  Removed
      BadNullConversion exception as a result.

    o Way back in v1.7.x we used the BadQuery exception for all kinds
      of exceptional conditions, not just bad queries.  Replaced
      most of these in v2.0.0 with new dedicated exceptions, but a
      few remained:
      
      - Errors that occur during the processing of a "use" query after
        the query itself executes correctly now throw UseQueryError.
        It's not a "bad query", because the query executed
        successfully.  It just choked during subsequent processing,
        so it's a different exception.  Thanks for this patch go to
        Jim Wallace.

      - Replaced BadQuery exceptions thrown in Row constructor due
        to bad ctor parameters with new ObjectNotInitialized exception
        This is also Jim Wallace's work.

    o The examples now all use getopt() type command line options
      instead of positional options.  This makes it possible to
      pass options in any order, leave at their default options that
      used to be in the middle of the sequence, and offer different
      subsets of options for different programs.  Also allows for
      special internal-use options, like -D passed by dtest to let
      examples change their behavior when run under dtest to produce
      only predictable output.

    o Split old libutil functionality into two modules, one holding
      all the "print data" functions, and another holding all the
      command line parsing stuff.  This makes it easier for newbies
      to ignore the command line stuff, treating it like a black box.
      The wish to understand the "print data" routines is much more
      common, so the two needed to be disentangled.

    o Renamed examples' libutil to libexcommon.

    o Removed connect_to_db() libutil function.  It combined command
      line parsing, which users don't care about, with database
      connection establishment, which they do care about.  Now the
      examples just call out to libexcommon to parse the command
      line, and use the values they get back to explicitly make the
      connection, so it isn't hidden.

    o Removed cchar and uint typedefs.

    o Redesigned dbinfo example's output to be easier to read.

    o Fixed an output formatting bug created in 2.3.0 that caused the
      tabular output from examples to not line up.

    o Renamed examples/tquery.cpp to tquery1.cpp.  Created tquery2.cpp
      to demonstrate passing parameters via a SQLQueryParametrs object
      instead of discretely.  Created tquery3.cpp for testing unquoted
      template parameters, such as integers.

    o Renamed fieldinf1.cpp example to fieldinf.cpp, and simplified
      its output so it can be part of the dtest sequence.

    o Renamed examples/xaction.cpp to transaction.cpp.  It created too
      much cognotive dissonance whenever thinking about both it and
      lib/transaction.cpp.

    o Added examples/deadlock.cpp, to test handling of exceptions due
      to server-side transaction deadlock detection.  Also added
      code to resetdb to create a table needed to test this.
      Initial version created by Jim Wallace to test the value of
      all his BadQuery exception work, with reworking by me.

    o Greatly expanded dtest suite.  Primary change is that we now
      have a handful of unit tests, where in v2.3.2 we only tested
      a subset of the examples.  Still very low coverage ratio,
      but it's a big improvement.

    o Optimized #includes, especially in lib/*.h to reduce
      dependencies and thus compile time when one of these changes.

    o Fixed a typo in RPM filename generation that prevented -devel
      RPM from recognizing that the corresponding MySQL++ library
      RPM was installed.

    o RPM spec file improvements by Remi Collet.

    o Renamed NO_LONG_LONGS to MYSQLPP_NO_LONG_LONGS to avoid a risk
      of collision in the global macro namespace.
    
    o First cut at Xcode2 project support.  Testing needed!

    o Debug build of library on VC++ and Xcode have a _d suffix now
      so you can have both versions of the library installed without
      conflict.

    o Moved the VC++ 2003 project files into a new vs2003 subdirectory
      because there are so many of them.  Also created vs2005
      subdirectory for VC++ 2005 and 2008 compatible project files.
      2005 makes an even bigger mess of the directory containing
      the .sln file, so the incentive is bigger.  Plus, we have to
      disable several things to get VC++ 2003 to build MySQL++ now,
      so we need a special 2005+ version of the project files for a
      complete build, if the user has one of the newer compilers.

    o ...plus dozens of small bug fixes and internal enhancements,
      many documentation improvements, and expansion of support for
      newer operating systems and compilers.


2.3.2, 2007.07.11 (r1669)

    o Previous release's const_string change caused more problems
      than it fixed.  This release contains the real fix. :)

    o New Connection::set_option() handling deals with the multi
      statements option correctly again.  examples/multiquery now
      runs again as a result.

    o Added new unit testing script, called dtest.  See the
      HACKERS file for details.  (This tool caught the previous
      two problems!)

    o Squished a GCC pedantic warning.  Thanks for the patch go to
      Andrew Sayers.


2.3.1, 2007.07.10 (r1659) The "After the Fireworks" release

    o const_string objects now keep a copy of their data, not
      just a pointer to it.  This is less efficient, but necessary
      to allow SSQLS to work with BLOBs.  Without this, we were
      seeing segfaults due to accessing freed memory pointed to
      by the const_string, because the underlying object went
      out of scope.

    o Fixed many more potential embedded null handling problems
      in manip.h.

    o MySQL++ can now optionally reference MySQL C API headers as
      being in a mysql subdirectory, a common thing on *ix systems,
      by defining MYSQLPP_MYSQL_HEADERS_BURIED before #including
      mysql++.h.

    o Restored ColData_Tmpl<T>::get_string(), removed in v2.3.0,
      along with warnings in the docs saying why you don't want
      to use it, and what your alternatives are.

    o VC++ and MinGW builds now define the HAVE_MYSQL_SSL_SET
      macro, which lets you use the C API's SSL features.
      This assumes your C API library does actually have these
      features enabled, which is the case with the official binary
      releases on Windows.  (Builds on *ix systems continue to
      test for these features at configure time.)

    o Fixed simple examples-only Makefile generation, for RPMs.


2.3.0, 2007.07.02 (r1645)

    o Added Query::for_each() and Query::store_if() methods
      proposed by Joel Fielder, and added examples for each.

    o It's now possible to store BLOB data in an SSQLS.  It's not
      foolproof, so added a section to the user manual (5.9) to
      document the method.  Also, changed examples/cgi_jpeg to use
      this new mechanism, instead of the ugly "raw row data" method
      it used to use.

    o Revamped Connection::set_option() handling.  These options
      used to be queued up, and applied only just before actually
      establishing the connection.  This made error reporting less
      helpful because the diagnostic was separated from the cause.
      Plus, the error messages were misleading to begin with.  Now,
      set_option() takes effect immediately if the connection is not
      yet up (excepting one special option that can actually be set
      after the connection is up) and issues better diagnostics when
      it detects errors.

    o Connection::connect() used to set a few options in such a
      way that the user couldn't override them.  Now it's smart enough
      to set them with the desired default values only when we see
      that the user hasn't given them other values.

    o SQLString can now be initialized from a mysqlpp::null,
      giving a "NULL" string.  This is useful for template queries.
      Patch by Michael Hanselmann.

    o resetdb error message about mixing library and header version
      numbers is now more explicit.

    o Changed BadConversion exception's "what" message text to be
      more like the other exceptions.  The inconsistency lead one
      to incorrectly copy-paste code from another exception handler,
      expecting it to behave the same way.  Now it does.

    o Added Row::raw_size(), as a shortcut for Row::at().size().

    o ssqls-pretty now detects when it's being run from within
      the MySQL++ distribution tree and gives a different -I flag
      to the compiler, so that it picks up the distribution headers
      instead of those that may be on the system already.

    o The quote manipulator now works for char[] correctly.
      Thanks for this patch go to Andrew Sayers.  (It's always
      worked for char*, but C++ doesn't consider that to be the
      same type, so it used the generic quote handling path,
      which doesn't do anything for char[].)

    o Fixed a build bug on older Solaris versions where the
      test for the C API library was erroneously failing, stopping
      the configuration process.

    o Simplified mysql_shutdown() level argument detection.
      Already had to do a version number ifdef check for the
      Windows case, so there's really no point to doing it with
      autoconf on Unixy platforms.  Moved version number check
      into lib/connection.cpp, and nuked the separate autoconf and
      Windows tests.

    o Removed dependency of sql_types.h on myset.h and (indirectly)
      datetime.h.  Now we only define sql_* typedef aliases for those
      MySQL++ types if the headers are included before sql_types.h.

    o Fixed a typo in one of the storein_sequence() template
      overloads, which is apparently rarely (or never?) used, because
      no one reported the compiler error you'd get if you tried.

    o Fixed a few more embedded null handling problems.

    o ColData used to keep two copies of all data it held.
      Now it keeps just one.

    o Fixed install.bat script to track the unified Bakefile change
      and the lack of separate debug and release builds under MinGW.

    o Yet another STLport + Query memory leak fix.

    o Squished a warning in newer GCCs having to do with identifier
      shadowing.  Patch by Jonathan Wakely.

    o Fixed a null-termination bug in Query::parse().  If you
      somehow constructed a query string without a terminating null
      character, then tried to parse it as a template query, it could
      walk off the end of the string.  Patch by Worster Chen.

    o Removed MYSQLPP_EXPORT tag from FieldNames and FieldTypes
      class declarations, as this can cause problems in programs
      that use vector<string> in VC++.  It has to do with multiply
      defined templates, since these classes derive from that
      template, and VC++ can't resolve the conflict without help.
      Since these classes aren't actually used outside the library,
      this shouldn't cause a problem.  Patch by Nils Woetzel.

    o Partial fix to Doxygen PDF build on RHEL4 and 5.  Needs
      hand-coaxing to complete successfully on RHEL4, and doesn't
      yet work at all on RHEL5.

    o Shortened the "no*" options to the bootstrap script, so that
      the usage message fits on a single line.

    o Added "nodoc" bootstrap script option, for disabling the
      documentation build during the dist target build.  Allows for
      building binary RPMs on CentOS 5.0, where doc building is
      currently broken.

    o Removed the updel example program.  It was kind of silly,
      and if you were to rewrite it today, you'd use for_each() anyway.

    o Lots of documentation improvements.


2.2.3, 2007.04.17 (r1538) The "Tax Day" release

    o Previous version left examples/vstudio/* out of the tarball
      by accident.

    o Improved generation of RPM temporary build directory path
      name generation.  Was using a hacked variant of the Fedora
      Packaging Guidelines' second best choice.  Now we're using
      the choice they recommend most highly, without changes.

    o Removed unnecessary resources from vstudio/wforms example.

    o Minor URL fix in refman


2.2.2, 2007.04.13 (r1526) The "Nervousmaking Friday the 13th" release

    o More small fixes to embedded null handling in Query.

    o Fixed a bug in single-parameter template query handling.

    o Added tquery example, to demonstrate proper use of template
      queries.  Previously, resetdb was the only exemplar, and
      it wasn't really suited for that.  This example also tests
      the previous item.

    o Added examples/vstudio/mfc, allowing us to improve the way
      we demonstrate Unicode handling.  Old way wasn't realistic.
      On *ix, people will depend on the terminal code to handle
      UTF-8.  On Windows, users are almost certain to be writing
      a GUI program, which requires different Unicode handling
      than the old examples showed.

    o Removed explicit Unicode conversion stuff from command line
      examples, and reworked the Unicode chapter in the user
      manual.
    
    o Added examples/vstudio/wforms to show integration with
      C++/CLI and Windows Forms.  Documented this in README.vc.

    o Rewrote load_file and cgi_image examples to be more
      useful, renaming them to load_jpeg and cgi_jpeg along
      the way.  Also, resetdb now creates a second table in the
      sample database for these two examples' use.  Also, added
      examples/logo.jpg to the distribution as sample data for
      these examples.

    o Limited the ostream base class casting stuff in Query to
      VC++ 2003, which is the only platform that really needed it.
      VC++ 2005 emits a warning with that hack in place, and on
      other platforms it's just replicating work that the compiler
      does already.

    o Added library version information to main library target
      so that systems that version shared libraries work as
      expected.  Thanks for this patch go to Jack Eidsness.

    o Merged much of the diffs between Remi Collet's RPM spec file
      into the official one.

    o Reorganized the doc subdir a bit.  Generated HTML is now all
      under doc/html instead of scattered under other subdirs,
      and renamed doc/README.mysql++ to doc/README.manuals.

    o Improvements to top-level manual building make targets:
      manuals now only rebuild at need, it's easier to request
      a rebuild of all manuals, and we force a rebuild attempt
      before building the distribution tarball so we don't ship
      outdated manuals.

    o Added ability to run examples under gdb using exrun,
      using same mechanism as we currently have for valgrind.
      Thanks for this patch go to Michael Hanselmann.

    o Added "Important Underlying C API Limitations" chapter to the
      user manual, to cover problems we keep seeing on the
      mailing list that are the result of ignorance of the way
      libmysqlclient behaves, not bugs MySQL++ is really in a
      position to fix.


2.2.1, 2007.02.28 (r1433)

    o Fixed the new localtime() alternative selection code
      for VS2003 and various uses of STLport.

    o No longer inserting a null character into the query stream
      on calling one of the preview() functions.  This was harmless
      in v2.1, which used C strings more extensively, but began
      causing problems in v2.2 due to its wider use of C++ strings.

    o Fixed a bug in the Connection copy ctor where it didn't
      completely initialize the object.

    o Optimized Query::preview_char() a bit.  Patch by Jonathan
      Wakely.

    o Reordered directory list used by autconf when locating the
      MySQL C API library.  The list is now ordered with the
      most likely locations for the library first, so we're less
      distracted by incorrect libraries.  This fixes a specific
      build error under RHEL4 with recent versions of MySQL 5.0.


2.2.0, 2007.01.23 (r1417)

    o ColData, const_string, and SQLString can now be constructed
      with an explicit length parameter.  Furthermore, Query
      class's execute(), store() and use() call chains terminate
      in a version taking an explicit length parameter, instead
      of one taking a simple C string.  Together, this means
      that it's now easier to handle data from the SQL server
      containing nulls.  The library is almost certainly not yet
      capable of handling embedded nulls in all cases, but this
      is a big first step towards that.

    o Can now construct a DateTime object from a time_t, and
      convert a DateTime back to a time_t.  Patch by Korolyov Ilya.

    o Changed the way we're handling exported functions in the
      Windows DLL case so that it works more reliably under MinGW.

    o Added proper copy semantics to Connection, so that you get a
      new connection with the same parameters, not just a bitwise
      copy of the object.

    o Using an explicitly thread-safe variant of localtime() for
      time conversions where one is available.

    o Removed ListInsert template from myset.h.  This wasn't used
      within the library, and was never documented, so I'm betting
      that no one actually uses it.

    o Result::copy() was not copying the exception flag in
      all cases.  Fix by Steven Van Ingelgem.

    o Added exrun shell script and exrun.bat files to distribution,
      to avoid linkage errors when running the examples while
      you still have an older version of MySQL++ installed.

    o Renamed MYSQLPP_LIB_VERSION to MYSQLPP_HEADER_VERSION, as
      what it really encodes is the version number in the mysql++.h
      file you're using, not the actual library version number.

    o Added mysqlpp::get_library_version(), which returns the
      library version number at build time.  Between this and
      the header version constant, you can check that you're not
      mixing MySQL++ header and library versions.

    o resetdb example uses these new version number affordances to
      double-check that you're not mixing libraries and headers
      from different versions.  This happens easily unless you
      take care of it (such as by using exrun) when you have one
      version of MySQL++ installed and you're trying to build and
      test a new version without blowing away the old one first
      or overwriting it.

    o No longer using recursive Makefiles on Unixy platforms
      or split lib + examples project files on VC++.  Everything is
      handled by a single top-level Makefile or project file, which
      is simpler for the end user, and makes better dependency
      management possible.

    o When looking for the MySQL C library on systems using
      autoconf, looking in .../lib64 wherever we are also looking
      in .../lib.

    o RPM build process no longer depends on Bakefile.  It means
      you have to build the examples when building an RPM even
      though they're never used within the RPM, but it's a better
      tradeoff in my opinion.

    o Updated include and library paths on Windows to reflect
      changes in the most recent MySQL installers.

    o Merged lib/defs.h and lib/platform.h into new file,
      lib/common.h.  Just cleans up the library internals.

    o Fixed build errors on Windows due to recent changes in MySQL.

    o Fixed a few memory leaks and double-deletes in Query class.

    o Fixed compatibility with STLPort's string implementation.
      Patch by dengxy at cse.buaa.edu.cn.

    o Fixed a compatibility problem between Set<> template and
      SSQLS.  Patch by Korolyov Ilya.

    o Fixed build bug in SQLQueryParms due to a character
      signedness issue on PowerPC with GCC.  Patch by Michael
      Hanselmann.

    o ~Transaction() can no longer throw exceptions.  It'll just
      quietly eat them, to avoid program termination.  Fix
      suggested by Alex Burton.

    o Fixed thread safety testing in autoconf case, accidentally
      broken during v2.1.0 development cycle.

    o Using Doxygen 1.5.1 to generate documentation.


2.1.1, 2006.04.04 (r1289)

    o MinGW and Cygwin will now build and link to mysqlpp DLLs.

    o Fixed bug in Query, causing it to initialize the "throw
      exceptions" flag incorrectly.  Thanks for this patch go to
      Joel Fielder.

    o Added -v flag for custom.pl script, which turns off the
      multiply-defined static variable fix.  Needed for VS 2003,
      which doesn't support variadic macros.  Also, added
      a diagnostic to detect the need for the -v flag, and
      suppressed the test for this feature in examples/util.cpp.


2.1.0, 2006.03.24 (r1269)

    o Converted automake and makemake files to their equivalents in
      Bakefile format.

    o Added the Transaction class, which makes it easy to use
      transaction sets in MySQL++.

    o Added xaction example to test new Transaction class.

    o Resetdb example now creates its example table using the
      InnoDB storage engine, in order to test the new transaction
      support.  Resetdb also declares the table as using UTF-8
      text; this doesn't change anything, but it does correctly
      document what we're doing.

    o Added sql_types.h header, containing C++ typedefs
      corresponding to each MySQL column type.  Using those new
      types in the type_info module, and in the SSQLS examples.

    o Replaced the way we were handling the template query
      version of Query member functions, to allow an arbitrary
      number of template query parameters.  By default, we
      now support 25 parameters, up from the old limit of 12.
      It's now possible to change just one number, run a script,
      and have a new limit.

    o Connection class does a better job of returning error
      messages if you call certain member functions that depend
      on a connection to the server before the connection is
      established.

    o Updated libmysqlclient.def for newer versions of MySQL.  (Fixes
      build errors having to do with mysql_more_results() and
      mysql_next_result().

    o Replaced final use of strcpy() with strncpy().

    o custom.pl now runs without complaint in strict mode, with
      warnings turned on.  Thanks for this patch go to "Waba".

    o Fixed a bug in custom.pl where incorrect code would be
      generated for some SSQLS set() methods.  Thanks for this
      patch go to "Waba".

    o SSQLS structures now support long and unsigned long fields.
      Thanks for this patch go to "Waba".

    o It's now possible to put SSQLS definitions in a header
      file used by multiple modules in a program without
      getting multiple static member definition errors.  See the
      documentation for details.  Thanks for this patch go to
      Viktor Stark.

    o Moved the definition of the 'stock' SSQLS out of the
      custom*.cpp example files and into a new stock.h file.
      Also, #including that file in the util module to test out
      the new SSQLS multiple static definition fix.

    o Using all of the digits of precision guaranteed by the
      IEEE 754 spec when stringizing floating point numbers
      to build queries.  Previously, we would use the platform
      default, which can be as few as 6 digits.

    o Removed lib/compare.h.  Not used within the library, never
      documented, and nobody seems to want to defend it.


2.0.7, 2005.11.23 (r1147)

    o Added explicit mysqlpp namespace qualifiers to generated code in
      custom*.h so you can use SSQLS in places where it doesn't make
      sense to say "using namespace mysqlpp" before the declaration.
      Also updated some of the examples to not have this "using"
      declaration to make it clear to users that it isn't needed, if you
      want to use explicit namespace qualifiers as well.  Thanks for
      this patch to Chris Frey.

    o Removed an apparently useless unlock() call from ResUse; there is
      no nearby lock() call, so if this unlock() is in fact necessary,
      it shouldn't be here anyway, because the two calls should be
      nearby each other.  Thanks for this patch to Chris Frey.

    o Fixed Query ostream initialization bug affecting SunPro CC (at
      least).  While this bug violates the Standard, it doesn't affect
      many real compilers because they don't enforce this rule.  Fixed
      by Chris Frey.

    o Previously, we only used the C99 style "long long" support when
      building under GNU CC.  This is now the default.  This should
      allow the code to work under SunPro CC.

    o Added another dynamic cast needed for proper Query ostream
      subclass overloading under VC++.  (7.1 at least...)

    o Detecting whether MySQL is built with SSL support on platforms
      using autotools.  Needed on some old Sun systems, for instance.
      Thanks for this patch to Ovidiu Bivolaru.

    o Fixed a potential memory bug in ColData's conversion to SQL null.

    o Many minor packaging tweaks.  (README clarifications, file
      permission fixes, better adherence to GNU packaging standards,
      etc.)

    
2.0.6, 2005.09.28 (r1123)

    o Fixed makemake.bat so it works on cmd.exe, not just 4NT.

    o Documentation fixes.


2.0.5, 2005.09.13 (r1114)

    o Visual C++ build now requires GNU make.  It is tested to work
      with either the Cygwin or the MinGW versions.  The previous
      version of MySQL++ used nmake.  This change enabled the
      following features:

        o Debug and Release versions are both built into
          separate subdirectories.

        o Dependency tracking for release version works
          correctly now.  (Previously dependencies worked
          only for debug version.)

        o 'make clean' removes release version binaries
          in addition to debug versions.

    o MinGW makemake support updated to support new release/debug
      subdirectory system.  This is probationary support, since
      this code currently can't be built as a DLL.  As a result,
      it is no more useful than the Cygwin version, for licensing
      reasons.

    o Several fixes to allow building on Solaris 8.  These fixes may
      also help on other SVR4-derived systems.

    o Removed Borland C++ makemake support, because this version
      of the library does not work completely, and there seems
      to be almost no user interest in fixing it.
      
    o Clarified "Handling SQL Nulls" section of user manual's
      Tutorial chapter.


2.0.4, 2005.08.29 (r1076)

    o Made mysql_shutdown() second parameter autoconf check less
      sensitive to compiler pedantry.

    o VC++ library Makefile is now smart enough to re-create the
      import library, if it is deleted while leaving the DLL alone.

    o Added libmysqlclient.def to tarball.

    o Reworked most of the top-level README* files.

    o Renamed LGPL file to LICENSE.


2.0.3, 2005.08.25 (r1060)

    o Visual C++ makemake system updated to build both debug and
      release versions of library DLL.

    o Fixed bug in simple1 example that caused crashes on Windows.

    o Doing UTF-8 to ANSI text translation in simple examples now.

    o Previous two releases built libmysqlpp with wrong soname on
      autotools-based systems.  Fixed.


2.0.2, 2005.08.18 (r1050)

    o Fixes to makemake system for cmd.exe.

    o Fixed the case where the system's C++ library includes an slist
      implementation in namespace std.


2.0.1, 2005.08.17 (r1046)

    o Added new simple1 example, showing how to retrieve just one
      column from a table.  Old simple1 is now called simple2, and
      simple2 is likewise shifted to simple3.

    o Added custom6 example, showing how to do the same thing with
      SSQLS.

    o Updated user manual to cover new examples.

    o Was accidentally shipping Subversion crap with tarball.  Fixed.


2.0.0, 2005.08.16 (r1031) The "Excess Hair Removal" release

    THIS IS NOT A DROP-IN REPLACEMENT FOR MySQL++ v1.7!

    At minimum, you will have to recompile your program against
    this library.  You may also have to make code changes.
    Please see the "Incompatible Library Changes" chapter of
    the user manual for a guide to migrating your code to this
    new version:

        http://tangentsoft.net/mysql++/doc/html/userman/breakages.html

    o The library's shared object file name (soname) scheme has
      changed.  (This mainly affects POSIX systems.)
      
      The soname for the last 1.7.x releases of MySQL++ was
      libmysqlpp.so.4, meaning the fourth version of the library's
      application binary interface (ABI).  (The first ABI version
      in this scheme was that provided by 1.7.9.)  MySQL++
      2.0.0's soname is libmysqlpp.so.2.0.0.  Since the dynamic
      linker setup on some systems will create a symlink to
      that file called libmysqlpp.so.2, it's possible that this
      library could be confused with that for MySQL++ 1.7.19
      through .21, which also used this number.  Do not install
      this library on a system which still has binaries linked
      against that version of the library!

      The new scheme is {ABI}.{feature}.{bug fix}.  That is,
      the first number changes whenever we break the library's
      binary interface; the second changes when adding features
      that do not break the ABI; and the last changes when the
      release contains only internal bug fixes.  This means
      that we will probably end up with MySQL++ 3.0 and 4.0 at
      some point, so there will be further soname conflicts.
      Hopefully we can put these ABI changes off long enough
      to avoid any real problems.

    o autoconf now installs headers into $prefix/include/mysql++,
      instead of $prefix/include.  If you were using the
      --includedir configure script option to get this behavior
      before, you no longer need it.

    o Linux binary RPMs will henceforth include only the
      libmysqlpp.so.X.Y.Z file, and create any short names
      required, to allow multiple versions to be installed at
      once.  Currently, you cannot install two MySQL++ library
      RPMs at once, because they both have /usr/lib/libmysqlpp.so.X,
      for instance.

    o Replaced the Visual C++ and Borland C++ project files with
      a new "makemake" system, which creates Makefiles specific
      to a particular toolchain.  This new mechanism also supports
      MinGW and generic GCC-on-*ix.  This was done partly to reduce
      the number of places we have to change when changing the
      file names in MySQL++ or adding new ones, and partly so we're
      not tied to one particular version of each of these tools.

    o VC++ Makefiles create a DLL version of the library only
      now, so there's no excuse for LGPL violations now.
      This same mechanism should make DLL builds under other
      Windows compilers easy.

    o Added Connection::enable_ssl(), which enables encrypted
      connections to the database server using SSL.

    o Connection::create_db() and drop_db() now return true on
      success, not false.

    o Connection::create_db() and drop_db() use Query::exec()
      now, for efficiency, rather than Query::execute().

    o Removed Connection::infoo().  Apparently just there to
      save you from a typo when calling the info() method, since
      it was a mere alias.

    o Renamed Connection::real_connect() to connect(), gave
      several more of its parameters defaults, and removed old
      connect() function.  Then changed user manual and examples
      to use new APIs.

    o Replaced Connection::read_option() with new set_option()
      mechanism.  The name change matches the method's purpose
      better.  Functional changes are that it returns true on
      success instead of 0, it supports a broader set of options
      than read_option() did, and it enforces the correct option
      argument type.

    o You can now call Connection::set_option() before the
      connection is established, which will simply queue the option
      request up until the connection comes up.  If you use this
      feature, you should use exceptions, because that's the only
      way an option setting failure can be signalled in this case.

    o Removed query-building functions (exec*(), store*(),
      use()) from class Connection, and moved all the implementation
      code to class Query.  Query no longer delegates the final
      step of sending the query to the database server to
      Connection().

    o Added Connection::enable_ssl(), for turning on SSL support on
      a connection.

    o Extracted exception disabling mechanism out of the many
      classes that had the feature into a new OptionalExceptions
      base class, which all classes having this feature now
      derive from.  Also, removed all per-method exception
      handling flags.  Finally, added NoExceptions class.  With
      all of these changes, there is now a common way to disable
      exceptions with fine granularity on all objects that
      support the feature.

    o All custom MySQL++ exceptions now derive from the new
      Exceptions class.  This regularizes the exception interface
      and allows you to use a single catch() block if you want.

    o The "throw exceptions" flag is passed from parent to child
      in all situations now.  (Or if not, please report it as
      a bug.) This fulfills a promise made in the v1.7.9 user
      manual, with the cost being that some programs will see
      new exceptions thrown that they're not expecting.

    o Added a bunch of new exception types: BadOption,
      ConnectionFailed, DBSelectionFailed, EndOfResults,
      EndOfResultSets, LockFailed, and ObjectNotInitialized.
      Some of these replace the use of BadQuery, which in v1.7.x
      was a kind of generic exception, thrown when something more
      specific wasn't available.  Beware, this means that programs
      may start crashing after recompiling them under v2.0 due to
      uncaught exceptions, if they were only trying to catch BadQuery.

      There are additional instances where the library will
      throw new exceptions.  One is when calling a method that
      forces the internals to use an out-of-bounds index on a
      vector; previously, this would just make the program
      likely to crash.  Another is that the library uses the
      BadFieldName exception -- created in v1.7.30 -- in more
      apropos situations.

    o Renamed SQLQueryNEParms to BadParamCount, to match naming
      style of other concrete exception types.

    o Extracted lock()/unlock() functions from Connection and
      Query classes into a new Lockable interface class.  Locking
      is implemented in terms of a different class hierarchy, Lock,
      which allows multiple locking strategies with a single ABI.

    o Removed ResUse::eof().  It's based on a deprecated MySQL
      C API feature, and it isn't needed anyway.

    o Removed arrow operator (->) for iterator returned by Fields,
      Result and Row containers.  It was inherently buggy, because
      a correct arrow operator must return the address of an
      object, but the underlying element access functions in these
      classes (e.g. at()) return objects by value, of necessity.
      Therefore, this operator could only return the address of
      a temporary, which cannot be safely dereferenced.

    o Returned Row subscripting to something more like the
      v1.7.9 scheme: there are two operator[] overloads, one for an
      integer (field by index) and another for const char* (field
      by name).  lookup_by_name() has been removed.  Because row[0]
      is ambiguous again, added Row::at() (by analogy with STL
      sequence containers), which always works.

    o Collapsed two of the Row::value_list*() overloads into
      two other similar functions using default parameters.
      This changes the API, but the removed functions aren't
      used within the library, and I doubt they are used outside,
      either.

    o Merged RowTemplate into Row.

    o Merged SQLQuery class into Query class.

    o Query is now derived from std::ostream instead of
      std::stringstream, and we manage our own internal string
      buffer.

    o Moved SQLParseElement and SQLQueryParms into their own
      module, qparms.

    o Added multiple result set handling to Query.  MySQL 4.1
      and higher allow you to give multiple SQL statements in a
      single "store" call, which requires extensions to MySQL++
      so you can iterate through the multiple result sets.  Also,
      stored procedures in MySQL 5.0 reportedly return multiple
      result sets.  Thanks for the initial patch go to Arnon Jalon;
      I reworked it quite a bit.

    o Query::storein*() now supports more varieties of the
      nonstandard slist comtainer.  (Singly-linked version of
      STL std::list.)

    o Template query mechanism and user manual had several
      mismatches.  Made manual match actual behavior, or
      made library match documented behavior, as apropriate.
      Initial patch by Jürgen MF Gleiss, with corrections and
      enhancements by Warren Young.

    o Collapsed mysql_* date and time base classes' methods and
      data into the subclasses.  Also, DateTime no longer derives
      from Date and Time; you could get away with that in the
      old hierarchy, but now it creates an inheritance diamond,
      and allows unsupported concepts like comparing a Time to
      a DateTime.

    o Removed "field name" form of Row::field_list().  It was
      pretty much redundant -- if you have the field names, why
      do you need a list of field names?

    o ColData can convert itself to bool now.  Thanks for this
      patch go to Byrial Jensen.

    o Removed simp_list_b type; wasn't being used, and doesn't
      look to be useful for end-user code.

    o Several methods that used to take objects by value now
      do so by const reference, for efficiency.

    o Several variable and function renamings so that MySQL++
      isn't needlessly tied to MySQL.  Even if we never make
      the library work with other database servers, there's
      little point in tying this library to MySQL blindly.

    o Renamed all private data members of MySQL++ classes to
      have trailing underscores.

    o 'private' section follows 'public' section in all classes
      now.

    o Removed mysql++.hh and sqlplus.hh backwards-compatibility
      headers.

    o Added copy ctors to Date/Time classes so that they will
      work in SSQLS under GCC 4.0.0.  Without these, the compiler
      couldn't make the conversion from raw MySQL row data.

    o Fixed a bunch of GCC 4.0 pedantic warnings: added virtual
      dtors to all base classes, calling base class ctors from leaf
      classes, etc.

    o All warnings fixed under VC++ at warning level 3.  (Mostly
      harmless signedness and integer conversion stuff.)

    o Updated LGPL license/copyright comments at the top of
      several files to use FSF's new physical address.

    o Relicensed user manual under a close variant of the Linux
      Documentation Project License, as it's designed for
      documentation, which the LGPL is not.  Permission for this
      received from Kevin Atkinson and MySQL AB.

    o Added ABI and API breakages chapter to user manual.  It
      is basically a subset of this ChangeLog, with only the
      information an end-user must know when migrating between
      versions.

    o Reworked user manual's DocBook code quite a bit after
      reading Bob Stayton's book "DocBook XSL" 3/e.  Better handling
      of stylesheets, taking advantage of some superior DocBook
      features, prettier output (especially the HTML version), etc.

    o Rewrote doc/userman/README to make it clearer how to get
      started contributing to the user manual.  It's essentially a
      "getting started with DocBook" guide now!

    o Lots of small text improvements to user and reference
      manuals.  Aside from the obvious tracking of library changes,
      made a bunch of minor style and clarity improvements.

    o Added CSS stylesheets for userman and refman to
      make the HTML versions of each a) not ugly; and b) match
      tangentsoft.net.  (Yes, some may say that these are incompatible
      goals....)

    o Standardized exception handling code in the examples that
      use it.

    o Fixed a potential memory leak due to exceptions thrown from
      ResUse.  Thanks for this patch go to Chris Frey.

    o Using new "no exceptions" feature of library in simple1
      example, so it is now truly simple.

    o simple1 example no longer depends as much on util module, so
      that all of the important code is in one place.  Makes
      learning MySQL++ a little less intimidating.

    o Added new simple2 and usequery examples, to demonstrate
      the proper way to handle a "use" query, with exceptions
      disabled, and not, respectively.  Added them to the user
      manual, in the appropriate place.

    o Refactored the "print stock table" example functions
      again, to make code using them clearer.

    o UTF-8 to UCS-2 handling in examples is now automatic on
      Windows.

    o Removed debug code from Windows Unicode output examples
      that slipped into previous release.

    o resetdb example is now clearer, and more robust in the
      face of database errors.

    o Simplified connect_to_db() in examples' util module.

    o Added sample autoconf macro for finding MySQL++ libraries, for
      people to use in their own autotools-based projects.

    o Lots and lots of minor cleanups not worth mentioning
      individually...


1.7.40, 2005.05.26 (r719)

    o Multiple item form of insert() now works if you're using the
      SQLQuery class, or its derivative, Query.  Thanks to Mark
      Meredino for this patch.

    o Fixed a bug in const_string::compare(), in which MySQL++
      would walk off the end of the shorter of the two strings.
      All was well if the two were the same length.

    o ResUse::operator=() now fully updates the object, so it's more
      like the behavior of the full ctor.

    o All source files now contain a license and copyright statement
      somewhere within them.

    o Optimized mysql++.h a bit: it now #includes only the minimum set
      of files required, and there is now an idempotency guard.
      This improves compile times a smidge, but mainly it was
      done to clean up the generated #include file graph in the
      reference manual.  Before, it was a frightful tangle because
      we #included everything except custom*.h.

    o Constness fix in MySQL++ date/time classes to avoid compiler
      warnings with SSQLS.  Thanks to Wolfram Arnold for this patch.

    o Fixed some compiler warnings in custom*.h.  Thanks to Chris Frey
      for this patch.

    o Added "Submitting Patches" and "Maintaining a Private CVS
      Repository" sections to the HACKERS file.  Thanks to Chris
      Frey for the source material for these sections.  The HACKERS
      file was improved in several other ways at the same time.

    o PDF version of user manual no longer has links to the reference
      manual.  They were ugly, and they were broken anyway due to the
      way we move the PDFs after generating them.  If you want
      interlinked manuals, use the HTML version.

    o PDF version of user manual now has hard page breaks between
      chapters.

    o Removed complic1 example.  Wasn't pulling its own weight.
      Everything it is supposed to demonstrate is shown in other
      examples already.

    o Refactored print_stock_table() in examples/util module to be
      four functions, and made all the examples use various of
      these functions where appropriate.  Before, several of
      the examples had one-off stock table printing code because
      print_stock_table() wasn't exactly the right thing, for one
      reason or another.  One practical problem with this is that
      some of the examples missed out on the recent Unicode updates;
      now such a change affects all examples the same way.

    o Since so many of the examples rely on the util module, the user
      manual now covers it.  The simple1 example in the user manual
      didn't make much sense before, in particular, because it's
      really just a driver for the util module.

    o Added custom5 example.  It shows how to use the equal_list()
      functionality of SSQLS.  Thanks to Chris Frey for the original
      version of this program.  (I simplified it quite a bit after
      accepting it.)

    o New user manual now covers the value_list(), equal_list() and
      field_list() stuff that the old manual covered but which was
      left out in previous versions of the new manaul.  Most of the
      examples are the same, but the prose is almost completely new.
      This new section includes the custom5 example.

    o Every declaration in MySQL++ is now documented in the reference
      manual, or explicitly treated as "internal only".

    o Improved docs for MySQL++'s mechanism to map between MySQL
      server types and C++ types.  Initial doc patch by Chris Frey,
      which I greatly reworked.

    o Improved a lot of existing reference manual documentation while
      adding the new stuff.

    o Expanded greatly on the exception handling discussion in the user
      manual.

    o Added all-new "Quoting and Escaping" section to the user
      manual's Tutorial chapter.  Moved some existing comments on
      quoting and escaping around and added some new ones to other
      sections as a result.

    o Added all-new "Handling SQL Nulls" section to the user manual's
      Tutorial chapter.

    o Many improvements to the Overview section of the user manual.

    o Row::operator[] reference now explains the right and wrong way to
      use the values it returns.  This is in response to a mailing list
      post where someone was incorrectly using this feature and getting
      a bunch of dangling pointers.

    o Updated Doxyfile so 1.3.19.1 parses it without warnings.  Still
      works with versions back to 1.2.18, at least.  (These are
      the versions shipped with Fedora Core 3 and Red Hat Linux 9,
      respectively.)

    o Using a superior method to make Doxygen ignore certain sections
      of the source code.  Between this change and the fact that
      everything not so ignored is documented, Doxygen no longer
      generates any warnings.

    o Lots of code style updates.  Everything should now be consistently
      formatted.


1.7.35, 2005.05.05 (r601) The "Cinco de Mayo" release

    o Added a "how to use Unicode with MySQL++" chapter to the user
      manual.  (Too bad "Cinco de Mayo" doesn't have any accented
      characters.  That would be just _too_ precious.)

    o VC++ examples now use the Unicode Win32 APIs, so they can display
      Unicode data from MySQL++.

    o Added an optional conversion function to examples/util.cpp to
      handle the conversion from UTF-8 to UCS-2 on Win32.

    o Moved "brief history of MySQL++" from intro section of refman to
      intro section of userman.

    o Lots of small bits of documentation polishing.
    
    o Made some minor constness fixes.  Thanks to Erwin van Eijk
      for this patch.

    o Made some warning fixes for GCC 4.0.  Not all warnings are
      fixed, because some of the needed changes would break the ABI.
      Thanks to Chris Frey for this patch.

    o Added lib/Doxyfile to distribution.
    

1.7.34, 2005.04.30 (r573)

    o Added a multiple-insert method for Query, which lets you insert
      a range of records from an STL container (or the whole thing,
      if you like) in a single SQL query.  This is faster, and it
      reduces coding errors due to less repetition.  Thanks to Mark
      Meredino for the patch.

    o Reference and user manual now get rebuilt automatically when
      required.  (E.g. on 'make dist', or explicitly now through 'make
      docs'.)

    o Made it easier to change the maximum number of SSQLS data members
      in generated custom-macros.h file.  It used to be hard-coded in
      several places in lib/custom.pl; now it's a variable at the top of
      the file.

    o Changed default SSQLS data member limit to 25, which is what it
      has been documented as for a long time now.  It was actually 26
      within custom.pl.

    o Fixed a regression in previous version.

    o Trimmed some fat from the distribution packages.

    o Some more small doucmentation improvements.


1.7.33, 2005.04.29 (r555)

    o Worked around an overloaded operator lookup bug in VC++ 7.1
      that caused SSQLS insert, replace and update queries to get
      mangled.  (Symptom was that custom2 and custom3 examples didn't
      work right.)  Thanks to Mark Meredino for digging up the
      following, which explains the problem and gives the solution:

      http://groups-beta.google.com/group/microsoft.public.vc.stl/browse_thread/thread/9a68d84644e64f15

    o Some VC++ warning fixes.

    o Major documentation improvements:
    
        o Using DocBook for user manual and Doxygen for reference
          manual.  The former now references the latter where
          useful.

        o Split out HACKERS and CREDITS files from main README,
          and improved remaining bits of README.

        o Moved the text from the old v1.7.9 LaTeX-based
          documentation over into the new systems, and reworked
          it to more closely resemble English.

        o Added a lot of new material to documentation, and
          simplified a lot of what already existed.

        o Documentation is now being built in HTML and PDF forms.

    o ebuild file updated to take advantage of recent configure script
      features.  Thanks to Chris Frey for this patch.



1.7.32, 2005.03.10 (r479)

    o Example building may now be skipped with --disable-examples
      configure script flag.

    o Changed stock items added in resetdb.  One is now UTF-8 encoded,
      to show that basic use of Unicode with MySQL++ is easy, yet not
      foolproof.  (See formatting of table on systems where cout isn't
      UTF-8 aware!)  Other stock items now follow a theme, for your
      amusement.  :)

    o custom3 example now changes UTF-8 item's name to the 7-bit ASCII
      equivalent.  Previously, this example would fix a spelling error
      in the table.

    o resetdb example now says 'why' when it is unable to create the
      sample database.

    o Small formatting change to print_stock_table(), used by several
      examples.

    o Was issuing a VC++-specific warning-disable pragma when built by
      any Windows compiler.  Fixed.
    

1.7.31, 2005.03.05 (r462) The "Inevitable Point-one Followup" release

    o Check for threads support must now be explicitly requested via
      configure script's new --enable-thread-check flag.

    o Fix for contacting MySQL server on a nonstandard port number.
      Thanks to Chris Frey for this patch.

    o Example programs using standard command line format now accept a
      fourth optional parameter, a port number for the server.  Thanks
      to Chris Frey for this patch.

    o One more g++ 3.4 pedantic warning fix by Chris Frey.

    o Exception handling in resetdb is no longer nested, because you'd
      get a segfault on some systems when an exception was thrown from
      one of the inner try blocks.

    o Improvements to Connection class's handling of locking mechanism.
      Concept based on patches by Rongjun Mu.

    o Implemented the declared-but-never-defined Query::lock().  Thanks
      to Rongjun Mu for this patch.
    
    o Cleaned up some unclear if/else blocks in connection.cpp by
      adding explicit braces, correct indenting and putting normal
      code path in the if side instead of the else.


1.7.30, 2005.02.28 (r443) The "Power of Round Numbers" release

    o bootstrap script now accepts a 'pedantic' argument, which sets a
      bunch of CFLAGS that make g++ very picky about the code it
      accepts without warnings.
      
    o Fixed a bunch of things that generated warnings with g++ in
      pedantic mode. Only two warnings remain, having to do with
      floating point comparisons.  (See Wishlist for plans on how to
      deal with these.)  Thanks to Chris Frey for this patch.

    o Split long tests out of configure.in into M4 files in new config
      subdir.  This makes configure.in easier to read.

    o Added preliminary thread support.  Currently, this just means that
      we detect the required compiler and linker thread flags, and link
      against the proper thread-safe libraries.  THERE MAY BE
      UN-THREAD-SAFE CODE IN MYSQL++ STILL!

    o Standard C++ exceptions are the default now.  Old pre-Standard
      exception stuff removed.

    o Row::lookup_by_name() will throw the new BadFieldName exception if
      you pass a bad field name.  Thanks for this patch to Chris Frey.

    o Row::operator[] will throw a Standard C++ out of bounds exception
      by way of std::vector::at() if you pass it a bad index.  Thanks
      for this patch to Chris Frey.

    o Setting Connection::is_connected flag to false on close().
      Previously, is_connected() would continue to return true after
      close() was called.

    o All number-to-string conversion ctors in SQLString class now use
      ostringstream to do the conversion.  Previously, we used
      snprintf(), which isn't available on all systems.  Also, we used a
      C99 format specifier for the "long long" conversion, which is also
      not available on all systems.  This new ostringstream code should
      be platform-independent, finally.


1.7.28, 2005.02.04 (r403)

    o --with-mysql* flags to configure script now try the given
      directory explicitly, and only if that fails do they try
      variations, like tacking '/lib' and such onto it to try and find
      the MySQL includes and libraries.  Thanks to Matthew Walton for
      the patch.

    o Finally removed sql_quote.h's dependence on custom.h, by moving
      the one definition it needed from custom.h to deps.h.  This will
      help portability to compilers that can't handle the SSQLS macros,
      by making that part of the library truly optional.


1.7.27, 2005.01.12 (r395)

    o configure check for libmysqlclient now halts configuration if the
      library isn't found.  Previously, it would just be flagged as
      missing, and MySQL++ would fail to build.

    o Added sql_string.cpp to VC++ and BCBuilder project files.

    o Removed Totte Karlsson's 'populate' example, which never made it
      into the distribution anyway.

    o Removed last vestiges of 'dummy.cpp'.

    o Renamed *.cc to *.cpp in BCBuilder project files.

    o Worked around a BCBuilder C++ syntax processing bug in row.h.


1.7.26, 2004.12.17 (r382)

    o Moved all of the SQLString definitions out of the header and into
      a new .cpp file, reformatted it all, and made the integer
      conversion functions use snprintf() or _snprintf() instead of
      sprintf().  Also, widened some of the buffers for 64-bit systems.

    o Using quoted #include form for internal library headers, to avoid
      some problems with file name clashes.  (The headers should still
      be installed in their own separate directory for best results,
      however.)  Thanks to Chris Frey and Evan Wies for the patch and
      the discussion that lead to it.

    o Removed unnecessary semicolons on namespace block closures.
      Thanks to Evan Wies for this patch.

    o Fixed namespace handling in the legacy headers mysql++.hh and
      sqlplus.hh.  Thanks to Chris Frey for this patch.

    o #including iostream instead of ostream in lib/null.h for
      broader C++ compatibility.  (This may allow MySQL++ to work on GCC
      2.95.2 again, but this is unconfirmed.)

    o Detecting proper mysql_shutdown() argument handling automatically
      in platform.h for the Windows compiler case instead of making the
      user edit the file.  Thanks to Evan Wies for this patch.
    
    o Fixed examples/Makefile.simple to use new *.cpp file naming.

    o Fix to Gentoo ebuild file's exception configure switch handling.
      Thanks to Chris Frey for this patch.

    o Rebuilding lib/custom*.h intelligently now, to avoid unnecessary
      recompiles after running bootstrap script.


1.7.25, 2004.12.09 (r360)

    o Yet more fixes to the --with-mysql-lib and --with-mysql-include
      flags.

    o Added DLLEXPORT stuff to platform.h, hopefully so that someone
      can figure out how to make VC++ make a DLL version of MySQL++.

    o Renamed *.cc to *.cpp.

    o Made 'set -> myset' change in VC++ project files.

    o Some style changes (mostly whitespace) in header files.


1.7.24, 2004.12.08 (r343)

    o Fixed the --with-mysql-lib and --with-mysql-include flags'
      behavior, and extended their search ability to handle one other
      common case.  (Fixed by Steve Roberts)

    o Fixes to put freestanding functions in namespace mysqlpp.  (They
      weren't in the namespace, while all the class member functions
      were.)  This required bumping the ABI version number to 4.
      
    o Renamed set module to myset, to avoid conflicts with Standard C++
      Library's set.h when MySQL++ headers were installed into one of
      the standard system include directories.

    o Renamed all the idempotency guards to make them consistent in
      style and unique to MySQL++.

    o Reformatted all of lib/*.cc.


1.7.23, 2004.11.20 (r333)

    o Query::reset() now empties the stored query string.  If you
      subsequently stored a longer query in the object, you'd overwrite
      the previous query, but otherwise the longer part of the previous
      one would stick out past the new query.

    o We now look to the NO_LONG_LONGS macro only to decide whether to
      fake 64-bit integer support using 32-bit integers.

    o 64-bit integer support under Visual C++ may be working now, using
      that platform's __int64_t type.  This has not been tested.

    o Removed 64-bit integer support for Codewarrior on Mac OS 9 and
      earlier.  OS X uses GCC, so it requires no special support.

    o Added MinGW detection in platform.h.
    
    o If you pass a flag (-X) to the examples that take the standard
      parameters (resetdb, simple1, etc.), it prints a usage message.
    
    o Better error handling in resetdb example, where errors are the
      most critical.  (If that one runs without errors, the others
      probably will, too, and you have to run that one first.)

    o resetdb now reports success, rather than succeeding silently.

    o Removed the code in sample1 example that duplicated util module's
      print_stock_table(), and called that function instead.

    o Moved the preview() calls in the example programs to before the
      query execution calls, because execution modifies the query.

    o All examples that take the standard command line parameters now 
      exit when connect_to_db() fails in one of the ways that don't
      throw an exception, rather than bulling onward until the next
      MySQL database call fails because the connection isn't up.

    o dbinfo example now takes the standard command line parameters.

    o Much better output formatting in dbinfo example.

    o Calling reset() where appropriate in the various example programs.
      Before, the programs may have worked, but not for the right
      reason.  This lead some people to believe that calling reset()
      was not necessary.

    o Fixed an incorrect use of row["string"] in complic1 example.

    o Lots of code style improvements to the examples.

    o Some VC++ type warnings squished.  Some remain.
    

1.7.22, 2004.11.17 (r302)

    o Applied patches by Zahroof Mohammed to allow it to build under GCC
      3.4.2.  Tested on MinGW and Fedora Core 3 systems.

    o Removed all the forward declarations in defs.h, and added
      forward declarations where necessary in individual header files.
      #including defs.h in fewer locations as a result.

    o Legacy headers sqlplus.hh and mysql++.hh now declare they are
      using namespace mysqlpp, to allow old code to compile against the
      new library without changes.

    o Removed query_reset parameter from several class Query member
      functions.  In the implementation, these parameters were always
      overridden!  No sense pretending that we pay attention to these
      parameters.  This changes the ABI version to 3.

    o #including custom.h in sql_query.h again...it's necessary on GCC
      3.4.
    
    o bootstrap script runs lib/config.pl after configure.  This is
      just a nicety for those running in 'maintainer mode'.


1.7.21, 2004.11.05 (r273)

    o Generating a main mysql++ RPM containing just the library files
      and basic documentation, and the -devel package containing
      everything else.

    o Devel package contains examples now, along with a new Makefile
      that uses the system include and library files, rather than the
      automake-based Makefile.am we currently have which uses the files
      in the mysql++ source directory.

    o Renamed sqlplusint subdirectory in the package to lib.

    o Removed the obsolete lib/README file.

    o lib/sql_query.h no longer #includes custom.h, simplifying
      build-time dependencies and shortening compile times.


1.7.20, 2004.11.03 (r258)

    o Collapsed all numbered *.hh headers into a single *.h file.  For
      example, the contents of row1.hh, row2.hh and row3.hh are now in
      row.h.

    o While doing the previous change, broke several circular
      dependencies.  (The numbered file scheme was probably partly done
      to avoid this problem.)  The practical upshot of most of these
      changes is that some functions are no longer inline.

    o Removed define_short.hh and everything associated with it.  The
      library now uses the short names exclusively (e.g. Row instead of
      MysqlRow).

    o Put all definitions into namespace mysqlpp.  For most programs,
      simply adding a 'using namespace mysqlpp' near the top of the
      program will suffice to convert to this version.

    o Once again, the main include file was renamed, this time to
      mysql++.h.  Hopefully this is the last renaming!

    o mysql++.hh still exists.  It emits a compiler warning that the
      file is obsolete, then it #includes mysql++.h for you.

    o sqlplus.hh is back, being a copy of the new mysql++.hh.  Both of
      these files may go away at any time.  They exist simply to help
      people transition to the new file naming scheme.

    o Renamed mysql++-windows.hh to platform.h, and added code to it to
      handle #inclusion of config.h on autotools-based systems
      intelligently.  This fixes the config.h error when building under
      Visual C++.

    o There is now only one place where conditional inclusion of
      winsock.h happens: platform.h.

    o Beautified the example programs.


1.7.19, 2004.10.25 (r186)

    o Fixed an infinite loop in the query mechanism resulting from the
      strstream change in the previous version.  There is an overloaded
      set of str() member functions that weren't a problem when query
      objects were based on strstream.
     
    o Query mechanism had a bunch of const-incorrectness: there were
      several function parameters and functions that were const for
      the convenience of other parts of the code, but within these
      functions the constness was const_cast away!  This was evil
      and wrong; now there are fewer const promises, and only one is
      still quietly broken within the code.  (It's in the SQLQuery
      copy ctor implementation; it should be harmless.)

    o Removed operator=() in Query and SQLQuery classes.  It cannot take
      a const argument for the same reason we have to cast away const
      in the SQLQuery copy ctor.  It's tolerable to do this in the copy
      ctor, but intolerable in an operator.  Since the copy ctor is good
      enough for all code within the library and within my own code, I'm
      removing the operator.

    o Above changes required bumping the ABI to version 2.

    o Visual C++ projects now look for MySQL build files in c:\mysql,
      since that's the default install location.  (Previously, it was
      c:\program files\mysql.)


1.7.18, 2004.10.01 (r177)

    o Changed all the strstream (and friends) stuff to stringstream type
      classes.  Let there be much rejoicing.

    o Query object now lets you use store() even when the SQL query
      cannot return a result, such as a DROP TABLE command.  This is
      useful for sending arbitrary SQL to the server.  Thanks to
      Jose Mortensen for the patch.

    o Quote fix in configure.in, thanks to David Sward.

    o Renamed undef_short file to undef_short.hh.

    o Gentoo ebuild file is actually being shipped with the tarball,
      instead of just sitting in my private CVS tree since 1.7.14 was
      current.  Ooops....


1.7.17, 2004.09.16 (r170)

    o Reverted one of the VC++ warning fix changes from 1.7.16 that
      caused crashes on Linux.

    o Added a configure test that conditionally adds the extra 'level'
      parameter to mysql_shutdown() that was added in MySQL 4.1.3 and
      5.0.1.


1.7.16, 2004.09.13 (r160)

    o Building VC++ version with DLL version of C runtime libraries, and
      at warning level 3 with no warnings emitted.

    o VC++ build no longer attempts to fake "long long" support.  See
      the Wishlist for further thoughts on this.


1.7.15, 2004.09.02 (r144)

    o Renamed Configure file to common.am, to avoid file name conflict
      with configure script on case-sensitive file systems.

    o Added ebuild file and ebuild target to top-level Makefile for
      Gentoo systems.  Thanks to Chris Frey for this.

    o Small efficiency improvements to BadQuery exception handling.
      Initial idea by Chris Frey, improvements by Warren Young.


1.7.14, 2004.08.26 (r130)

    o Builds with Visual C++ 7.1.

    o Fixed a bug in custom macro generation that caused problems with
      GCC 3.4.  (X_cus_value_list ctor definition was broken.)


1.7.13, 2004.08.23 (r92)

    o Removed USL CC support.  (System V stock system compiler.)  Use
      GCC on these platforms instead.

    o Added examples/README, explaining how to use the examples, and
      what they all do.

    o Most of the example programs now accept command line arguments for
      host name, user name and password, like resetdb does.

    o Renamed sinisa_ex example to dbinfo.

    o Several Standard C++ syntax fixes to quash errors emitted by
      GCC 3.4 and Borland C++ Builder 6.  Thanks to Steffen Schumacher
      and Totte Karlsson for their testing and help with these.

    o Added proper #includes for BCBuilder, plus project files for same.
      Thanks to Totte Karlsson for these.


1.7.12, 2004.08.19 (r63)

    o Many Standard C++ fixes, most from the GCC 3.4 patch by
      Rune Kleveland.

    o Added Wishlist file to distribution.

    o Fixed a problem in the bootstrap script that caused complaints
      from the autotools on some systems.

    o RPM building is working properly now.

    o Fixed the idempotency guard in datetime1.hh.


1.7.11, 2004.08.17 (r50)

    o Renamed mysql++, defs and define_short files, adding .hh to the
      end of each.  (They're header files!)  This shouldn't impact
      library users, since these are hopefully used internal to the
      library only.

    o Removed sqlplus.hh file.  Use mysql++.hh instead.
    
    o Added mysql++.spec, extracted from contributed 1.7.9 source RPM, 
      and updated it significantly.  Also, added an 'rpm' target to
      Makefile.am to automate the process of building RPMs.

    o Added bootstrap and LGPL files to distribution tarball.

    o Added pre-1.7.10 history to this file.

    o Removed .version file.  Apparently it's something required by old
      versions of libtool.


1.7.10, 2004.08.16 (r27)

    o Maintenance taken over by Warren Young (mysqlpp at etr dash usa
      dot com.) See http://lists.mysql.com/plusplus/3326 for details.

    o Applied many of the GCC 3.x patches submitted for 1.7.9 over
      the years.  This allows it to build on everything from 3.0 to
      3.3.3, at least.  Because so many patches are rolled up in one
      big jump, it's difficult to describe all the changes and where
      they came from.  Mostly they're Standard C++ fixes, as GCC
      has become more strict in the source code that it will accept.

    o MysqlRow used to overload operator[] for string types as well as
      integers so you could look up a field by its name, rather than by
      its index.  GCC 3.3 says this is illegal C++ due to ambiguities in
      resolving which overload should be used in various situations.
      operator[] is now overloaded only for one integer type, and a
      new member function lookup_by_name() was added to maintain the old
      by-field-name functionality.

    o Fixed another operator overloading problem in SSQLS macro
      generation with GCC 3.3.

    o The _table member of SSQLS-defined structures is now const char*,
      so you can assign to it from a const char* string.

    o Got autoconf/automake build system working with current versions
      of those tools again.  Removed the generated autotools files from
      CVS.

    o Renamed library file from libsqlplus to libmysqlpp.


1.7.9 (May 1 2001) Sinisa Milivojevic <sinisa@mysql.com>

    * Fixed a serious bug in Connection constructor when reading MySQL
    * options
    * Improved copy constructor and some other methods in Result /
    * ResUse
    * Many other minor improvements
    * Produced a complete manual with chapter 5 included
    * Updated documentation, including a Postscript format

1.7.8 (November 14 2000) Sinisa Milivojevic <sinisa@mysql.com>

    * Introduced a new, standard way of dealing with C++ exceptions.
    * MySQL++ now supports two different methods of tracing exceptions.
    * One is by the fixed type (the old one) and one is standard C++
    * type by the usage of what() method. A choice of methods has to be
    * done in building a library. If configure script is run with
    * -enable-exception option , then new method will be used. If no
    * option is provided, or -disable-exception is used, old MySQL++
    * exceptions will be enforced. This innovation is a contribution of
    * Mr. Ben Johnson <ben@blarg.net>
    * MySQL++ now automatically reads at connection all standard MySQL
    * configuration files
    * Fixed a bug in sql_query::parse to enable it to parse more then 99
    * char's
    * Added an optional client flag in connect, which will enable usage
    * of this option, e.g. for getting matched and not just affected
    * rows. This change does not require any changes in existing
    * programs
    * Fixed some smaller bugs
    * Added better handling of NULL's. Programmers will get a NULL
    * string in result set and should use is_null() method in ColData to
    * check if value is NULL
    * Further improved configuration
    * Updated documentation, including a Postscript format

1.7.6 (September 22 2000) Sinisa Milivojevic <sinisa@mysql.com>

    * This release contains some C++ coherency improvements and scripts
    * enhacements
    * result_id() is made available to programmers to fetch
    * LAST_INSERT_ID() value
    * Connection constroctur ambiguity resolved, thanks to marc@mit.edu
    * Improved cnnfigure for better finding out MySQL libraries and
    * includes
    * Updated documentation, including a Postscript format

1.7.5 (July 30 2000) Sinisa Milivojevic <sinisa@mysql.com>

    * This release has mainl bug fixes  and code improvements
    * A bug in FieldNames::init has been fixed, enabling a bug free
    * usage of this class with in what ever a mixture of cases that is
    * required
    * Changed behaviour of ResUse, Result and Row classes, so that they
    * could be re-used as much as necessary, without any memory leaks,
    * nor with any re-initializations necessary
    * Fixed all potential leaks that could have been caused by usage of
    * delete instead of delete[] after memory has been allocated with
    * new[]
    * Deleted all unused classes and macros. This led to a reduction of
    * library size to one half of the original size. This has
    * furthermore brought improvements in compilation speed
    * Moved all string manipulation from system libraries to
    * libmysqlclient, thus enabling uniformity of code and usage of 64
    * bit integers on all platforms, including Windows, without
    * reverting to conditional compilation. This changes now requires
    * usage of mysql 3.23 client libraries, as mandatory
    * Changed examples to reflect above changes
    * Configuration scripts have been largely changed and further
    * changes shall appear in consecutive sub-releases. This changes
    * have been done and shall be done by our MySQL developer Thimble
    * Smith <tim@mysql.com>
    * Changed README, TODO and text version of manual. Other versions of
    * manual have not been updated
    * Fixed .version ``bug''. This is only partially fixed and version
    * remains 1.7.0 due to some problems in current versions of libtool.
    * This shall be finally fixed in a near future
    * Several smaller fixes and improvements
    * Added build.sh script to point to the correct procedure of
    * building of this library. Edit it to add configure options of your
    * choice

1.7 (May17 2000) Sinisa Milivojevic <sinisa@mysql.com>

    * This is mainly a release dealing with bug fixes, consistency
    * improvements and easier configure on some platforms
    * A bug in fetch_row() method of ResUse class has been fixed. Beside
    * changes that existed in a distributed patch, some additional error
    * checking has been introduced
    * A bug in escape manipulator has been fixed that could cause an
    * error if all characters had to be escaped
    * An inconsistency in column indexing has been fixed. Before this
    * version, column names in row indexing with strings, i.e.
    * row[<string>] , has been case sensitive, which was inconsistent
    * with MySQL server handling of column names
    * An inconsistency in conversion from strings to integers or floats
    * has been fixed. In prior version a space found in data would cause
    * a BadConversion exception. This has been fixed, but 100%
    * consistency with MySQL server has not been targeted, so that other
    * non-numeric characters in data will still cause BadConversion
    * exception or error. As this API is used in applications, users
    * should provide feedback if full compatibility with MySQL server is
    * desired, in which case BadConversion exception or error would be
    * abolished in some of future versions
    * A new method in ColData class has been introduced. is_null()
    * method returns a boolean to denote if a column in a row is NULL.
    * Finally, as of this release, testing for NULL values is possible.
    * Those are columns with empty strings for which is_null() returns
    * true.
    * Some SPARC Solaris installations had C++ exception problems with
    * g++ 2.95.2 This was a bug that was fixed in GNU gcc, as from
    * release 2.95 19990728. This version was thoroughly tested and is
    * fully functional on SPARC Solaris 2.6 with the above version of
    * gcc.
    * A 'virtual destructor ' warning for Result class has been fixed
    * Several new functions for STL strings have been added. Those
    * functions (see string_util.hh) add some of the functionality
    * missing in existing STL libraries
    * Conversion for 64 bit integers on FreeBSD systems has been added.
    * On those systems _FIX_FOR_BSD_ should be defined in CXXFLAGS prior
    * to configuring. Complete conversion to the usage of functions for
    * integer conversion found in mysqlclient library is planned for one
    * of the next releases
    * A completely new, fully dynamic, dramatic and fully mutable result
    * set has been designed and will be implemented in some of 2.x
    * releases
    * Several smaller fixes and improvements, including defaulting
    * exceptions to true, instead of false, as of this version
    * An up-to-date and complete Postscript version of documentation is
    * included in this distribution
    * Large chunks of this manual are changed, as well as README and
    * TODO files.

1.6 (Feb 3 2000) Sinisa Milivojevic <sinisa@mysql.com>

    * This is a major release as it includes new features and major
    * rewrites
    * Automatic quoting and escaping with streams. It works
    * automatically , depending on the column type. It will work with <<
    * on all ostream derived types. it is paricularly handy with query
    * objects and strstreams. Automatic quoting and escaping on cout,
    * cerr and clog stream objects is intentionally left out, as quoting
    * / escaping on those stream objects is not necessary. This feature
    * can be turned of by setting global boolean dont_quote_auto to
    * true.
    * Made some major changes in code, so that now execute method should
    * be used only with SSQL and template queries, while for all other
    * query execution of UPDATE's, INSERT's, DELETE's, new method exec()
    * should be used. It is also faster.
    * New method get_string is inroduced for easier handling / casting
    * ColData into C++ strings.
    * Major rewrite of entire code, which led to it's reduction and
    * speed improvement. This also led to removal of several source
    * files.
    * Handling of binary data is introduced. No application program
    * changes are required. One of new example programs demonstrates
    * handling of binary data
    * Three new example programs have been written and thoroughly
    * tested. Their intention is to solve some problems addressed by
    * MySQL users.
    * Thorough changes is Makefile system has been made
    * Better configuration scripts are written, thanks to D.Hawkins
    * <dhawkins@cdrgts.com>
    * Added several bug fixes
    * Changed Manual and Changelog

1.5 (Dec 1 1999) Sinisa Milivojevic <sinisa@mysql.com>

    * Fixed bug in template queries, introduced in 1.4 (!)
    * Fixed connect bug
    * Fixed several bug in type_info classes
    * Added additional robustness in classes
    * Added additional methods for SQL type info
    * Changed Changelog and README

1.4 (Nov 25 1999) Sinisa Milivojevic <sinisa@mysql.com>

    * Fixed bug in store and storein methods
    * Fixed one serious memory leak
    * Fixed a very serious bug generated by gcc 2.95.xx !!
    * Added robustness in classes, so that e.g. same query and row
    * objects can be re-used
    * Changed sinisa_ex example to reflect and demonstrate this
    * stability
    * Changed Changelog and README
    * Few other bug fixes and small improvements and speed-ups

1.3 (Nov 10 1999) Sinisa Milivojevic <sinisa@mysql.com>

    * Fixed several erronous definitions
    * Further changed source to be 2.95.2 compatible
    * Expunged unused statements, especially dubious ones, like use of
    * pointer_tracker
    * Corrected bug in example file fieldinf1
    * Finally fixed mysql_init in Connection constructor, which provided
    * much greater stability !
    * Added read and get options, so that clients, like mysqlgui can use
    * it
    * Changed Changelog and README
    * Many other bug fixes.

1.2 (Oct 15 1999) Sinisa Milivojevic <sinisa@mysql.com>

    * First offical release. Version 1.0 and 1.1 were releases by Sinisa
    * before I (Kevin Atkinson) made him the offical maintainer,
    * Many manual fixes.
    * Changed README and Changelog
    * Changed source to be compilable by gcc 2.95.xx, tribute to Kevin
    * Atkinson <kevinatk@home.com>
    * Added methods in Connection class which are necessary for
    * fullfilling administrative functions with MySQL
    * Added many bug fixes in code pertaining to missing class
    * initializers , as notified by Michael Rendell <michael@cs.mun.ca>
    * Sinisa Milivojevic <sinisa@mysql.com> is now the offical
    * maintainer.

1.1 (Aug 2 1999) Sinisa Milivojevic <sinisa@mysql.com>

    * Added several bug fixes
    * Fixed memory leak problems and variables overlapping problems.
    * Added automake and autoconf support by loic@ceic.com
    * Added Makefile for manual
    * Added support for cygwin
    * Added example sinisa_ex (let modesty prevail) which used to crash
    * a lot when memory allocation, memory leak and overlap problems
    * were present. Smooth running of this example proves that all those
    * bugs are fixed
    * Corrected bugs in sql_query.cc regarding delete versus delete[]
    * and string length in manip.cc
    * Changed manual
    * Changed README
    * Many other smaller things

1.0 (June 9 1999) Michael Widenius <monty@monty.pp.sci.fi>

    * Added patches from Orion Poplawski <orion@bvt.com> to support the
    * UnixWare 7.0 compiler

.64.1.1a (Sep 27 1998)

    * Fixed several bugs that caused my library to fail to compile with
    * egcs 1.1. Hopefully it will still compile with egcs 1.0 however I
    * have not been able to test it with egcs 1.0.
    * Removed some problem causing debug output in sql++pretty.

.64.1a (Aug 1 1998)

    * Added an (almost) full guide to using Template Queries.
    * Fixed it so the SQLQuery will throw an exception when all the
    * template parameters are not provided.
    * Proofread and speedchecked the manual (it really needed it).
    * Other minor document fixes.

.64.0.1a (July 31 1998)

    * Reworked the Class Reference section a bit.
    * Minor document fixes
    * Added more examples for SSQLS.
    * Changed the syntax of equal_list for SSQLS from equal_list (cchar
    * *, Manip, cchar *) to (cchar *, cchar *, Manip).
    * Added set methods to SSQLS. These new methods do the same thing as
    * there corresponding constructors.
    * Added methods for creating a mysql_type_info from a C++ type_info.

.64.a (July 24 1998)

    * Changed the names of all the classes so they no longer have to
    * have Mysql in the begging of it. However if this creates a problem
    * you can define a macro to only use the old names instead.
    * The Specialized SQL Structures (formally known as Custom Mysql
    * Structures) changed from mysql_ to sql_.
    * Added the option of using exceptions thoughout the API.
    * ColData (formally known as MysqlStrings) will now throw an
    * exception if there is a problem in the conversion.
    * Added a null adapter.
    * Added Mutable Result Sets
    * Added a very basic runtime type identification for SQL types
    * Changed the document format from POD to LYX .
    * Am now using a modified version of Perceps to extract the class
    * information directly from the code to make my life easier.
    * Added an option of defining a macro to avoid using the automatic
    * conversion with binary operators.
    * Other small fixed I probully forgot to mentune.

.63.1.a

    * Added Custom Mysql Structures.
    * Fixed the Copy constructor of class Mysql
    * Started adding code so that class Mysql lets it children now when
    * it is leaving
    * Attempted to compile it into a library but still need help. As
    * default it will compile as a regular program.
    * Other small fixes.

.62.a (May 3 1998)

    * Added Template Queries
    * Created s separate SQLQuery object that is independent of an SQL
    * connection.
    * You no longer have to import the data for the test program as the
    * program creates the database and tables it needs.
    * Many small bug fixes.

.61.1.a (April 28 1998)

    * Cleaned up the example code in test.cc and included it in the
    * manual.
    * Added an interface layout plan to the manual.
    * Added a reverse iterator.
    * Fixed a bug with row.hh (It wasn't being included because of a
    * typo).

.61.0.a

    * Major interface changes. I warned you that the interface may
    * change while it is in pre-alpha state and I wasn't kidding.
    * Created a new and Separate Query Object. You can no longer execute
    * queries from the Mysql object instead you have to create a query
    * object with Mysql::query() and use it to execute queries.
    * Added the comparison operators to MysqlDate, MysqlTime and
    * MysqlDateTime. Fixed a few bugs in the MysqlDate... that effected
    * the stream output and the conversion of them to strings.
    * Reflected the MysqlDate... changes in the manual.
    * Added a new MysqlSet object and a bunch of functions for working
    * with mysql set strings.

.60.3a (April 24 1998)

    * Changed strtoq and strtouq to strtoll and strtull for metter
    * compatibility Minor Manual fix.
    * Changed makefile to make it more compatible with Solaris (Thanks
    * Chris H)
    * Fixed bug in comparison functions so that they would compare in he
    * right direction.
    * Added some items to the to do list be sure to have a look.

Changes to README.txt.

1
2
3
4
5
6
7
8



9






10







11
12
13
14

15


16

17




18
19

20
21



22

23






24
25
26
27

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
56



57
58


59


60

61
62


63
64
65

66
67
68

69



70
71
72



73
74
75






76
77


78


79
80
81
82
83






84






85

86
87
88

89

90



91


92
93
94
95
96
97
98
99



100
101
102
103
104
105

106

107




108
109
110








111
112
113
114
115
116






117



118
119
120
121


122
123
124
125
126
127
128
What It Is
~~~~~~~~~~
    MySQL++ is a C++ wrapper for MySQL's C API.  It is built around STL
    principles, to make dealing with the database as easy as dealing
    with an STL container.  MySQL++ relieves the programmer of dealing
    with cumbersome C data structures, generation of repetitive SQL
    statements, and manual creation of C++ data structures to mirror
    the database schema.










    Its home page is http://tangentsoft.net/mysql++/









Prerequisites
~~~~~~~~~~~~~

    To build MySQL++, you must have the MySQL C API development


    files installed.






    On Unixy systems (Linux, Mac OS X, Cygwin, *BSD, Solaris...),
    the MySQL development files are installed if you build MySQL

    from source.  If you installed MySQL as a binary package, then
    the development files are often packaged separately from the



    MySQL server itself.  It's common for the package containing the

    development files to be called something like "MySQL-devel".







    If you're building on Windows with Visual C++ or MinGW, you
    need to install the native Win32 port of MySQL from mysql.com.
    The development files are only included with the "complete"

    version of the MySQL installer, and some versions of this
    installer won't actually install them unless you do a custom
    install.  Another pitfall is that MySQL++'s project files assume
    that you've installed the current General Availability release of
    MySQL (v5.0 right now) and it's installed in the default location.
    If you've installed a different version, or if MySQL Inc. changes

    the default location (which they seem to do regularly!) you'll have
    to adjust the link and include file paths in the project settings.









Additional Things to Read
~~~~~~~~~~~~~~~~~~~~~~~~~
    Each major platform we support has a dedicated README-*.txt



    file for it containing information specific to that platform.
    Please read it.





    For authorship information, see the CREDITS.txt file.






    For license information, see the COPYING.txt file.




    If you want to change MySQL++, see the HACKERS.txt file.

    You should have received a user manual and a reference manual
    with MySQL++.  If not, you can read a recent version online:




        http://tangentsoft.net/mysql++/doc/

    Search the MySQL++ mailing list archives if you have more
    questions:




        http://lists.mysql.com/plusplus/







Building the Library
~~~~~~~~~~~~~~~~~~~~


    MySQL++ uses Bakefile (http://bakefile.org/) to generate
    platform-specific project files and makefiles from a single set
    of input files.  We currently support these build systems:


    autoconf:
        For Unixy platforms, including Linux, Mac OS X, and Cygwin, in

        addition to the "real" Unices.  See README-Unix.txt for general



        instructions.  Supplementary platform-specific details are
        in README-Cygwin.txt, README-Linux.txt, README-Mac-OS-X.txt,
        and README-Solaris.txt.




    MinGW:
        We ship Makefile.mingw for MinGW.  It currently only builds the






        static version of the library for technical reasons.  This has
        licensing ramifications.  See README-MinGW.txt for details.





    Visual C++:
        We ship Visual Studio 2003, 2005, and 2008 project files.
        No older version of Visual C++ will build MySQL++, due to
        compiler limitations.  See README-Visual-C++.txt for more
        details.













    Xcode:

        We ship an Xcode v2 project file.  It hasn't been tested
        much yet, since the autoconf method works just fine on OS X.
        As a result, we need both success and failure reports on the

        mailing list.  See README-Mac-OS-X.txt for more information.








Example Programs
~~~~~~~~~~~~~~~~
    You may want to try out the programs in the examples subdirectory
    to ensure that the MySQL++ API and your MySQL database are both
    working properly.  Also, these examples give many examples of
    the proper use of MySQL++.  See README-examples.txt for further
    details.





Unsupported Compliers
~~~~~~~~~~~~~~~~~~~~~
    If you're on Windows but want to use some other compiler besides
    Visual C++ or GCC, you are currently on your own.  There have
    been past efforts to port MySQL++ to other Windows compilers,

    but for one reason or another, all of these ports have died.






    On Unixy systems, GCC still works best.  "Native" compilers and
    third-party compilers may work, but you're on your own to get
    it working.









    We have nothing in particular against these unsupported systems.
    We just lack the time and resources to support everything
    ourselves.  If you are sufficiently motivated to get MySQL++
    working on one of these alternate systems, see the HACKERS.txt
    file first for guidance.  If you follow the advice in that file,






    your patch will be more likely to be accepted.





If You Want to Hack on MySQL++...
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~


    If you intend to change the library or example code, please read
    the HACKERS.txt file.

    If you want to change the user manual, read doc/userman/README.txt

    If you want to change the reference manual, see the Doxygen manual:
    http://www.stack.nl/~dimitri/doxygen/manual.html
|
|
|
|
|
|
|
|
>
>
>

>
>
>
>
>
>
|
>
>
>
>
>
>
>




>
|
>
>
|
>

>
>
>
>
|
|
>
|
|
>
>
>
|
>
|
>
>
>
>
>
>

<
<
|
>
|
<
|
<
|
|
>
|
|
>
>
>
>

>
>
>
|
<
<
<
>
>
>
|
<
>
>
>
>

<

>
>
>
>
>
|

>
>
>
|

<
<
>
>

>
|

<
|
>
>
>

<
>
>

>
>

>
|
|
>
>
|
<
<
>

|
|
>
|
>
>
>
|
<
<
>
>
>

|
<
>
>
>
>
>
>
|
|
>
>

>
>
|
<
|
|
<
>
>
>
>
>
>

>
>
>
>
>
>
|
>
|
<
<
>
|
>

>
>
>

>
>
|
<
<
|
<
<
<

>
>
>

<
<
|
|
|
>
|
>

>
>
>
>
|
|
|
>
>
>
>
>
>
>
>

|
|
|
|
|
>
>
>
>
>
>
|
>
>
>


|
|
>
>
|
|
|
<

<
<
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
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
56
57
58
59


60
61
62

63

64
65
66
67
68
69
70
71
72
73
74
75
76
77



78
79
80
81

82
83
84
85
86

87
88
89
90
91
92
93
94
95
96
97
98
99


100
101
102
103
104
105

106
107
108
109
110

111
112
113
114
115
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
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
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233

234


Visual C++ Version Compatibility
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    MySQL++ is fully functional with Visual C++ 2005 and 2008.

    MySQL++ also works with VC++ 2003 (a.k.a. VC++ 7.1), with the
    exception of the SSQLS feature.  There was partial support for
    SSQLS with VC++ 2003 in MySQL++ v2, but a feature we added in
    MySQL++ v3.0 crashes this version of the compiler, so we had to
    remove support for it entirely.  MySQL++ automatically disables
    SSQLS when you build it with VC++ 2003.  As long as you avoid
    using that feature of the library, you should be fine.

    Older versions of Visual C++ are basically hopeless when it
    comes to building current versions of MySQL++.  They have too
    many weaknesses in their Standard C++ implementation to build a
    modern library like MySQL++.  If you cannot upgrade your compiler,
    my advice is that you're best off programming straight to the
    MySQL C API rather than try to make MySQL++ build.

    There are two sets of .sln and .vcproj files shipped with MySQL++:
    one for Visual C++ 2003 in the vc2003 subdirectory, and another
    set for VC++ 2005 and newer in vc2005.  The only difference
    between them is that the VC++ 2003 versions omit SSQLS related
    files from the build.  If you're using VC++ 2008, use the vc2005
    project files; Visual Studio will walk you through the conversion
    process, which will do the right thing.


Prerequisites
~~~~~~~~~~~~~
    You need to have the Windows version of the MySQL server installed
    on your development system, even if you always access a MySQL
    server on a different machine.  This is because in addition to
    installing the server itself, the official MySQL Windows binaries
    also install the client-side development files that MySQL++
    needs in order to communicate with a MySQL server.

    You have to do a Custom install to enable installation of these
    development files.  If you get an error about mysql-version.h or
    mysql.h when building MySQL++, go back and reinstall the MySQL
    server, paying careful attention to the options.

    If you've installed the development files and are still getting
    header file include errors, read on.


Building the Library and Example Programs
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    If you installed the MySQL server somewhere other than 
    
        C:\Program Files\MySQL\MySQL Server 5.0\
        
    you need to change the project file settings.  If you're willing to
    install Bakefile (see below), you can do this quickly by changing
    the variable MYSQL_WIN_DIR at the top of the file mysql++.bkl,
    then regenerating the project files by running rebake.bat.
    Otherwise, you'll need to change the include and library paths
    in all of the project files by hand.



    You must build both the Debug and Release versions of the library,
    because a release build of your program won't work with a Debug
    version of the MySQL++ DLL.  Since version 3.0, the VC++ build

    of MySQL++ names these two DLLs differently: mysqlpp_d.dll for

    the Debug version, and mysqlpp.dll for the Release version.
    This lets you keep them in the same PATH directory, without a
    concern as to whether the correct one will be used.

    With the library built, run at least the resetdb and simple1
    examples to ensure that the library is working correctly.
    In addition to the other generic examples, there are a few
    Visual C++ specific examples that you might want to look at in
    examples\vstudio.  See README-examples.txt for further details.

    Once you're sure the library is working correctly, you can run
    the install.hta file at the project root to install the library
    files and headers in a directory of your choosing.
    



    (Aside: You may not have come across the .hta extension before.
    It's for a rarely-used feature of Microsoft's Internet Explorer,
    called HTML Applications.  Know what Adobe AIR is?  Kinda like
    that, only without the compilation into a single binary blob,

    the cross-platform compatibility, and the power of Flash and
    ActionScript 3.  These limitations don't cause a problem here.
    In fact, AIR would be vast overkill here.  Just open install.hta
    in a text editor to see how it works.)



Using MySQL++ in an MFC Project
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    If you don't already have a project set up, open Visual Studio,
    say File > New > Project, then choose Visual C++ > MFC > MFC
    Application.  Go through the wizard setting up the project as
    you see fit.

    Once you have your project open, right click on your top-level
    executable in the Solution Explorer, choose Properties, and make
    the following changes.  (Where it doesn't specify Debug or Release,
    make the same change to both configurations.)



        o Append the following to C/C++ > General > Additional Include
          Directories:

            C:\Program Files\MySQL\MySQL Server 5.0\include,
            C:\mysql++\include


        o Under C/C++ > Code Generation change "Runtime Library" to
          "Multi-threaded Debug DLL (/MDd)" for the Debug
          configuration.  For the Release configuration, make it
          "Multi-threaded DLL (/MD)".


        o Append the following to Linker > General > Additional Library
          Directories for the Debug configuration:

            C:\Program Files\MySQL\MySQL Server 5.0\lib\debug,
            C:\mysql++\vc\debug

          For the Release configuration, make it the same, but
          change the 'debug' directory names to 'opt'.

        o Under Linker > Input add the following to "Additional
          Dependencies" for the Debug configuration:



            libmysql.lib wsock32.lib mysqlpp_d.lib

          ...and then for the Release configuration:
          
            libmysql.lib wsock32.lib mysqlpp.lib

          This difference is because MySQL++'s Debug DLL and import
          library have a _d suffix so you can have both in the same
          directory without conflicts.



    You may want to study examples\vstudio\mfc\mfc.vcproj to see
    this in action.  Note that some of the paths will be different,
    because it can use relative paths for mysqlpp.dll.



Using MySQL++ in a Windows Forms C++/CLI Project
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    Before you start work on getting MySQL++ working with your own
    program, you need to make some changes to the MySQL++ build
    settings.  Open mysqlpp.sln, then right-click on the mysqlpp
    target and select Properties.  Make the following changes for
    both the Debug and Release configurations:

        o Under Configuration Properties > General, change "Common
          Language Runtime support" to the /clr setting.

        o Under C/C++ > Code Generation, change "Enable C++ Exceptions"
          from "Yes (/EHsc)" to "Yes With SEH Exceptions (/EHa)"


    If you have already built MySQL++, be sure to perform a complete
    rebuild after changing these options.  The compiler will emit

    several C4835 warnings after making those changes, which are
    harmless when using the DLL with a C++/CLI program, but which
    warn of real problems when using it with unmanaged C++.  This is
    why MySQL++'s Windows installer (install.hta) offers the option
    to install the CLR version into a separate directory; use it if
    you need both managed and unmanaged versions installed!

    For the same reason, you might give some thought about where you
    install mysqlpp.dll on your end user's machines when distributing
    your program.  My recommendation is to install it in the same
    directory as the .exe file that uses it, rather than installing
    into a system directory where it could conflict with a mysqlpp.dll
    built with different settings.

    Once you have MySQL++ built with CLR support, open your program's
    project.  If you don't already have a project set up, open Visual


    Studio, say File > New > Project, then choose Visual C++ > CLR >
    Windows Forms Application.  Go through the wizard setting up the
    project as you see fit.

    The configuration process isn't much different from that for an
    MFC project, so go through the list above first.  Then, make the
    following changes particular to .NET and C++/CLI:

        o Under Configuration Properties > General change the setting
          from /clr:pure to /clr.  (You need mixed assembly support
          to allow a C++/CLI program to use a plain C++ library


          like MySQL++.)




        o For the Linker > Input settings, you don't need wsock32.lib.
          The mere fact that you're using .NET takes care of that
          dependency for you.



    In the MFC instructions above, it said that you need to build it
    using the Multi-threaded DLL version of the C++ Runtime Library.
    That's not strictly true for MFC, but it's an absolute requirement
    for C++/CLI.  See the Remarks in this MSDN article for details:

        http://msdn2.microsoft.com/en-us/library/k8d11d4s.aspx

    You may want to study examples\vstudio\wforms\wforms.vcproj to
    see all this in action.  Note that some of the paths will be
    different, because it can use relative paths for mysqlpp_d.dll
    and mysqlpp.dll.


Working With Bakefile
~~~~~~~~~~~~~~~~~~~~~
    MySQL++'s top-level Visual Studio project files aren't
    maintained directly.  Instead, we use a tool called Bakefile
    (http://bakefile.org/) to generate many different project file
    and Makefile types from a single set of source files.  There is
    a native Windows version of Bakefile up on that web site.
    Download that and put the directory containing bakefile_gen.exe
    in your Windows PATH.

    Bakefile generates the various project files and Makefiles from
    a single source file, mysql++.bkl.  This is usually the file you
    need to change when you want to make some change to the MySQL++
    build system.

    While Bakefile's documentation isn't as comprehensive as it
    ought to be, you can at least count on it to list all of the
    available features.  So, if you can't see a way to make Bakefile
    do something, it's likely it just can't do it.  Bakefile is a
    high-level abstraction of build systems in general, so it'll never
    support all the particulars of every odd build system out there.

    Once you've made your changes, you can generate the Visual C++
    project files by running rebake.bat, which you can find in the
    same directory as this file.


If You Run Into Problems...
~~~~~~~~~~~~~~~~~~~~~~~~~~~
    Especially if you have linking problems, make sure your project
    settings match the above.  Visual C++ is very picky about things
    like run time library settings.  When in doubt, try running one
    of the example programs.  If it works, the problem is likely in
    your project settings, not in MySQL++.




Changes to abi.xml.in.















1


















2
3
4



























5




6
7






8
9



























































<version>


















    @MYSQLPP_VERSION_MAJOR@.@MYSQLPP_VERSION_MINOR@.@MYSQLPP_VERSION_BUGFIX@
</version>
<headers>



























    lib




</headers>
<libs>






    .
</libs>













































>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
|
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
>
>
>
|
|
>
>
>
>
>
>
|
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
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
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
# This file is free software; you can redistribute it and/or modify it
# under the terms of the GNU Lesser General Public License as published
# by the Free Software Foundation; either version 2.1 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
# Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public
# License along with MySQL++; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
# USA

# Standard autotools stuff
AC_INIT(mysql++, 3.2.2, plusplus@lists.mysql.com, mysql++)
AC_CONFIG_HEADER(config.h)
AC_CONFIG_MACRO_DIR([config])
AC_CANONICAL_SYSTEM


# Enable libtool to decide shared library compile flags (ie -fPIC)
AC_PROG_LIBTOOL
AC_SUBST([LIBTOOL_DEPS])


# Break package version up into major, minor and bugfix components.
MYSQLPP_VERSION_MAJOR=`echo $PACKAGE_VERSION | cut -f1 -d.`
AC_SUBST(MYSQLPP_VERSION_MAJOR)
MYSQLPP_VERSION_MINOR=`echo $PACKAGE_VERSION | cut -f2 -d.`
AC_SUBST(MYSQLPP_VERSION_MINOR)
MYSQLPP_VERSION_BUGFIX=`echo $PACKAGE_VERSION | cut -f3 -d.`
AC_SUBST(MYSQLPP_VERSION_BUGFIX)


# Check for Standard C support
AC_PROG_CC
AC_HEADER_STDC


# Figure out whether/how to handle threading support, if available.
AC_ARG_ENABLE(thread-check,
		[  --enable-thread-check  Check for threads, and use if available. ],
		[ thread_check=yes ])
if test "x$thread_check" = "xyes"
then
	ACX_PTHREAD
	LIBS="$PTHREAD_LIBS $LIBS"
	CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
	CC="$PTHREAD_CC"
	AC_CHECK_HEADERS(synch.h)
	AC_CHECK_HEADERS(unistd.h)
fi


# Let caller provide -f to lib/*.pl scripts in a uniform way
AC_ARG_WITH([field-limit],
		AS_HELP_STRING([--with-field-limit=<n>],
			[set max template query and SSQLS field count]),
		[], [])
if test -n "$with_field_limit"
then
	 ( cd lib ;
	   ./querydef.pl -f $with_field_limit ;
	   ./ssqls.pl -f $with_field_limit 
	 )
fi


# Try to find local getopt(); if we fail, we'll use the one in lib/cmdline.*
AC_CHECK_FUNC(getopt, 
		[AC_DEFINE(HAVE_POSIX_GETOPT, [], Define if getopt() is available in unistd.h)],
		[AC_CHECK_LIB(iberty, getopt,
			[AC_DEFINE(HAVE_LIBIBERTY_GETOPT, [], Define if getopt() is available in libiberty.h)],
			[])])


# Checks for libraries and local system features
LIB_MATH
LIB_SOCKET_NSL
MYSQL_C_API_LOCATION
MYSQL_WITH_SSL
AX_C_LOCALTIME_R
AC_CHECK_LIB(intl, main)


# If this is Cygwin, add a linker flag to suppress a silly link message.
case "${host}" in
	*cygwin*)
		LDFLAGS="$LDFLAGS -Wl,--enable-auto-import"
		;;
esac


# Check for Standard C++ support, and extensions.  This must be near
# the end, because the CPLUSPLUS directive makes autoconf use C++
# compiler for all subsequent tests!
AC_PROG_CXX
AC_LANG_CPLUSPLUS
STL_SLIST_EXTENSION


# Include Bakefile macros
AC_BAKEFILE([m4_include(config/autoconf_inc.m4)])


#
# Configure process complete; write out files generated from *.in.
#
AC_OUTPUT([\
	doc/userman/userman.dbx \
	install.hta \
	lib/Doxyfile \
	lib/mysql++.h \
	ssx/Doxyfile \
	abi.xml \
	mysql++.spec \
	Makefile \
	version
])
chmod +x version

Changes to bmark.txt.

1
2

3
4
5
6
7
8
9
10
11
12



13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
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
56
57
58
59
60
61
62
63
64


65
66
67
68
69
70
71
72
73
74
75
76
77
78
79

80
81
82
83
84
85
86
87
88
89
90
91
92
93



94
95
96


97
98
99
100
101
102
103
104
105
106
107
108
109
110
111

112
113
114
115
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
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

191
192
193
194
195
196
197




198
199
200
201
202
203
204
205
206


207




208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242






243
244
245
246
247
248

249
250
251
252
253
254
255
256
257
All unit tests passed
---------------- BEGIN resetdb OUTPUT ----------------

Connecting to database server...
Dropping existing sample data tables...
Creating stock table...
Populating stock table...inserted 4 rows.
Creating empty images table...
Creating deadlock testing tables...
Reinitialized sample database successfully.
================ END resetdb OUTPUT ================

---------------- BEGIN simple1 OUTPUT ----------------



We have:
	Nürnberger Brats
	Pickle Relish
	Hot Mustard
	Hotdog Buns
================ END simple1 OUTPUT ================

---------------- BEGIN simple2 OUTPUT ----------------
Item                           Num       Weight    Price     Date

Nürnberger Brats              97        1.5       8.79      2005-03-10
Pickle Relish                  87        1.5       1.75      1998-09-04
Hot Mustard                    73        0.95      0.97      1998-05-25
Hotdog Buns                    65        1.1       1.10      1998-04-23
================ END simple2 OUTPUT ================

---------------- BEGIN simple3 OUTPUT ----------------
Item                           Num       Weight    Price     Date

Nürnberger Brats              97        1.5       8.79      2005-03-10



Pickle Relish                  87        1.5       1.75      1998-09-04
Hot Mustard                    73        0.95      0.97      1998-05-25
Hotdog Buns                    65        1.1       1.10      1998-04-23
================ END simple3 OUTPUT ================

---------------- BEGIN store_if OUTPUT ----------------



Records found: 2

Item                           Num       Weight    Price     Date

Nürnberger Brats              97        1.5       8.79      2005-03-10
Hot Mustard                    73        0.95      0.97      1998-05-25
================ END store_if OUTPUT ================

---------------- BEGIN for_each OUTPUT ----------------
There are 322 items weighing 416.85 stone and costing 1147.19 cowrie shells.
================ END for_each OUTPUT ================

---------------- BEGIN multiquery OUTPUT ----------------
Multi-query: 
DROP TABLE IF EXISTS test_table; CREATE TABLE test_table(id INT); INSERT INTO test_table VALUES(10); UPDATE test_table SET id=20 WHERE id=10; SELECT * FROM test_table; DROP TABLE test_table
Result set 0 is empty.
Result set 1 is empty.
Result set 2 is empty.
Result set 3 is empty.
Result set 4 has 1 row:
  +----+
  | id |
  +----+
  | 20 |
  +----+
Result set 5 is empty.


Stored procedure query: 
DROP PROCEDURE IF EXISTS get_stock; CREATE PROCEDURE get_stock( i_item varchar(20) ) BEGIN SET i_item = concat('%', i_item, '%'); SELECT * FROM stock WHERE lower(item) like lower(i_item); END;
Result set 0 is empty.
Result set 1 is empty.
Query: CALL get_stock('relish')
Result set 0 has 1 row:
  +---------------+-----+--------+-------+------------+-------------+
  |          item | num | weight | price |      sdate | description |
  +---------------+-----+--------+-------+------------+-------------+
  | Pickle Relish |  87 |    1.5 |  1.75 | 1998-09-04 |        NULL |
  +---------------+-----+--------+-------+------------+-------------+
Result set 1 is empty.
================ END multiquery OUTPUT ================

---------------- BEGIN tquery1 OUTPUT ----------------

Query: select * from stock
Records found: 4

Item                           Num       Weight    Price     Date

Nuerenberger Bratwurst         97        1.5       8.79      2005-03-10
Pickle Relish                  87        1.5       1.75      1998-09-04
Hot Mustard                    73        0.95      0.97      1998-05-25
Hotdog Buns                    65        1.1       1.1       1998-04-23
================ END tquery1 OUTPUT ================

---------------- BEGIN resetdb OUTPUT ----------------
Connecting to database server...
Dropping existing sample data tables...



Creating stock table...
Populating stock table...inserted 4 rows.
Creating empty images table...


Creating deadlock testing tables...
Reinitialized sample database successfully.
================ END resetdb OUTPUT ================

---------------- BEGIN tquery2 OUTPUT ----------------
Query: select * from stock
Records found: 4

Item                           Num       Weight    Price     Date

Nuerenberger Bratwurst         97        1.5       8.79      2005-03-10
Pickle Relish                  87        1.5       1.75      1998-09-04
Hot Mustard                    73        0.95      0.97      1998-05-25
Hotdog Buns                    65        1.1       1.1       1998-04-23
================ END tquery2 OUTPUT ================


---------------- BEGIN tquery3 OUTPUT ----------------
Stuff we have a lot of in stock:
	Nuerenberger Bratwurst
	Pickle Relish
================ END tquery3 OUTPUT ================



---------------- BEGIN tquery4 OUTPUT ----------------
Query: update stock set num = 70 where num < 70
Query: select * from stock
Records found: 4

Item                           Num       Weight    Price     Date

Nuerenberger Bratwurst         97        1.5       8.79      2005-03-10
Pickle Relish                  87        1.5       1.75      1998-09-04
Hot Mustard                    73        0.95      0.97      1998-05-25
Hotdog Buns                    70        1.1       1.1       1998-04-23

Query: select * from stock where weight > 1.2 or description like '%Mustard%'
Records found: 3

Item                           Num       Weight    Price     Date

Nuerenberger Bratwurst         97        1.5       8.79      2005-03-10
Pickle Relish                  87        1.5       1.75      1998-09-04
Hot Mustard                    73        0.95      0.97      1998-05-25
================ END tquery4 OUTPUT ================

---------------- BEGIN resetdb OUTPUT ----------------
Connecting to database server...
Dropping existing sample data tables...
Creating stock table...
Populating stock table...inserted 4 rows.
Creating empty images table...
Creating deadlock testing tables...
Reinitialized sample database successfully.
================ END resetdb OUTPUT ================

---------------- BEGIN ssqls1 OUTPUT ----------------
We have:
	Nürnberger Brats
	Pickle Relish
	Hot Mustard (good American yellow mustard, not that European stuff)
	Hotdog Buns
================ END ssqls1 OUTPUT ================

---------------- BEGIN ssqls2 OUTPUT ----------------
Query: INSERT INTO `stock` (`item`,`num`,`weight`,`price`,`sDate`,`description`) VALUES ('Hot Dogs',100,1.5,NULL,'1998-09-25',NULL)




Query: select * from stock
Records found: 5

Item                           Num       Weight    Price     Date

Nürnberger Brats              97        1.5       8.79      2005-03-10
Pickle Relish                  87        1.5       1.75      1998-09-04
Hot Mustard                    73        0.95      0.97      1998-05-25
Hotdog Buns                    65        1.1       1.1       1998-04-23
Hot Dogs                       100       1.5       (NULL)    1998-09-25
================ END ssqls2 OUTPUT ================



---------------- BEGIN ssqls3 OUTPUT ----------------
Query: UPDATE `stock` SET `item` = 'Nuerenberger Bratwurst',`num` = 97,`weight` = 1.5,`price` = 8.7899999999999991,`sDate` = '2005-03-10',`description` = NULL WHERE `item` = 'Nürnberger Brats'
Query: select * from stock
Records found: 5

Item                           Num       Weight    Price     Date

Nuerenberger Bratwurst         97        1.5       8.79      2005-03-10
Pickle Relish                  87        1.5       1.75      1998-09-04
Hot Mustard                    73        0.95      0.97      1998-05-25
Hotdog Buns                    65        1.1       1.1       1998-04-23
Hot Dogs                       100       1.5       (NULL)    1998-09-25
================ END ssqls3 OUTPUT ================

---------------- BEGIN ssqls4 OUTPUT ----------------
Records found: 5

Item                           Num       Weight    Price     Date


Hot Dogs                       100       1.5       (NULL)    1998-09-25
Hot Mustard                    73        0.95      0.97      1998-05-25
Hotdog Buns                    65        1.1       1.1       1998-04-23
Nuerenberger Bratwurst         97        1.5       8.79      2005-03-10
Pickle Relish                  87        1.5       1.75      1998-09-04





Currently 65 hotdog buns in stock.
================ END ssqls4 OUTPUT ================

---------------- BEGIN ssqls5 OUTPUT ----------------
Custom query:
select * from stock where `weight` = 1.5 and `price` = 8.7899999999999991
================ END ssqls5 OUTPUT ================

---------------- BEGIN ssqls6 OUTPUT ----------------


Query: select * from stock




Records found: 26

Item                           Num       Weight    Price     Date

Tiny Screws                    1000      0.01      0.05      2008-11-11
Needle-nose Pliers             50        0.5       5.95      2008-11-12
Small Soldering Iron           40        0.5       15.95     2008-09-01
Large Soldering Iron           35        0.75      24.95     2008-08-01
Solder Wick                    100       0.1       2.95      2008-04-01
Mini Screwdrivers, 3 pc.       30        0.4       8.95      2008-03-25
Mini Screwdrivers, 6 pc.       40        0.6       12.95     2008-04-01
Wire-wrapping Tool             25        0.2       4.95      2008-04-23
Red LED, 5mm, 3000mcd          300       0.01      0.29      2008-10-02
Orange LED, 5mm, 2500mcd       250       0.01      0.29      2008-07-31
Yellow LED, 5mm, 3000mcd       400       0.01      0.25      2008-09-30
Green LED, 5mm, 1000mcd        350       0.01      0.45      2008-09-27
Blue LED, 5mm, 3900mcd         500       0.01      0.34      2007-12-01
White LED, 5mm, 15000mcd       750       0.01      0.43      2008-02-01
AA Battery, single             220       0.05      0.5       2007-09-19
AA Battery, 4-pack             60        0.2       1.79      2007-08-03
AA Battery, 24-pack            8         1.2       9.99      2007-04-25
C Battery, single              100       0.075     0.65      2007-11-14
C Battery, 4-pack              25        0.3       2.29      2007-06-05
C Battery, 24-pack             5         1.8       10.99     2007-06-13
D Battery, single              180       0.08      0.7       2007-12-03
D Battery, 4-pack              45        0.3       2.59      2007-04-01
D Battery, 24-pack             12        1.9       11.99     2007-05-15
9-volt Battery, single         90        0.06      0.75      2008-01-02
9-volt Battery, 3-pack         17        0.2       1.99      2008-02-28
9-volt Batter, 20-pack         12        1.2       12.99     2007-12-28
================ END ssqls6 OUTPUT ================

---------------- BEGIN load_jpeg OUTPUT ----------------
Inserted "NULL" into images table, 0 bytes, ID 1
================ END load_jpeg OUTPUT ================







---------------- BEGIN cgi_jpeg OUTPUT ----------------
Content-type: text/plain

No image content!
================ END cgi_jpeg OUTPUT ================


--- BEGIN ssqlsxlat -i examples/common.ssqls -o ERROR OUTPUT ---
==== END ssqlsxlat -i examples/common.ssqls -o ERROR OUTPUT ====
--- BEGIN ssqlsxlat -i examples/stock.ssqls -o ERROR OUTPUT ---
==== END ssqlsxlat -i examples/stock.ssqls -o ERROR OUTPUT ====
--- BEGIN ssqlsxlat -i test/test1.ssqls -o ERROR OUTPUT ---
==== END ssqlsxlat -i test/test1.ssqls -o ERROR OUTPUT ====
--- BEGIN ssqlsxlat -i test/test2.ssqls -o ERROR OUTPUT ---
==== END ssqlsxlat -i test/test2.ssqls -o ERROR OUTPUT ====
<
<
>
|
<
<
<
<
<
<
<

<
>
>
>
|
<
<
<
<
<

<
<
|
<
<
<
<
<

<
<
|
<
>
>
>
<
<
<
<

<
>
>
>
|

<
|
<
<
<
|
<
<
<
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
>
>
<
<
<
<
<
<
<
<
<
<
<
<
<

<
>
|
<

<
|
<
<
<
<
<

<
<
<
>
>
>
|
<
<
>
>
<
<
<

<
<
<
|
<

<
<
<
<
<
>
|
<
<
<
|
<
>
>

<
|
|
<
|
<

<
<
<
<

<
<
|
<
|
<
<
<
<
|
<
|
<
<
<
<
<
<
<

<
<
<
<
<
|
<

<
<
>
>
>
>
<
<

<

<
<
<
<
<
<
>
>
|
<
<
|
<

<
|
<
<
<
<
<
<
|
<
|
|
<
>
|
<
<
<
<
<

>
>
>
>
|
<
|
<
<
<
<

<
>
>
|
>
>
>
>
|
|
|
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<

<
<
<
>
>
>
>
>
>
|
<
<

<
<
>
|
<
<
<
<
<
<
<
<


1
2







3

4
5
6
7





8


9





10


11

12
13
14




15

16
17
18
19
20

21



22



23














24
25













26

27
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







56





57

58


59
60
61
62


63

64






65
66
67


68

69

70






71

72
73

74
75





76
77
78
79
80
81

82




83

84
85
86
87
88
89
90
91
92
93
94



























95



96
97
98
99
100
101
102


103


104
105










/***********************************************************************
 test/cpool.cpp - Tests the ConnectionPool class.









 Copyright (c) 2007-2008 by Educational Technology Resources, Inc. and
 (c) 2007 by Jonathan Wakely.  Others may also hold copyrights on
 code in this file.  See the CREDITS.txt file in the top directory of
 the distribution for details.








 This file is part of MySQL++.








 MySQL++ is free software; you can redistribute it and/or modify it

 under the terms of the GNU Lesser General Public License as published
 by the Free Software Foundation; either version 2.1 of the License, or
 (at your option) any later version.






 MySQL++ is distributed in the hope that it will be useful, but WITHOUT
 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
 License for more details.


 You should have received a copy of the GNU Lesser General Public



 License along with MySQL++; if not, write to the Free Software



 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301














 USA
***********************************************************************/















#include <cpool.h>
#include <connection.h>



#include <iostream>









#if defined(MYSQLPP_PLATFORM_WINDOWS)
#	define SLEEP(n) Sleep((n) * 1000)
#else
#	include <unistd.h>


#	define SLEEP(n) sleep(n)
#endif







using namespace std;







class TestConnection : public mysqlpp::Connection
{



public:

	TestConnection() : itime_(time(0)) { }
	time_t instantiation_time() const { return itime_; }


private:
	time_t itime_;

};









class TestConnectionPool : public mysqlpp::ConnectionPool

{




public:

	~TestConnectionPool() { clear(); }













	unsigned int max_idle_time() { return 1; }




private:
	TestConnection* create() { return new TestConnection; }
	void destroy(mysqlpp::Connection* cp) { delete cp; }
};











int
main()
{


	TestConnectionPool pool;



	mysqlpp::Connection* conn1 = pool.grab();






	mysqlpp::Connection* conn2 = pool.grab();

	if (conn1 == conn2) {
		cerr << "Pool returned the same connection twice!" << endl;

		return 1;
	}






	pool.release(conn2);
	mysqlpp::Connection* conn3 = pool.grab();
	if (conn2 != conn3) {
		cerr << "conn2 should have been reused but wasn't!" << endl;
		return 1;

	}






	time_t itime_c1 = dynamic_cast<TestConnection*>(conn1)->
			instantiation_time();
	pool.release(conn1);
	SLEEP(pool.max_idle_time() + 1);
	mysqlpp::Connection* conn4 = pool.grab();
	time_t itime_c4 = dynamic_cast<TestConnection*>(conn4)->
			instantiation_time();
	if (itime_c1 == itime_c4) {
		cerr << "conn1 should have been destroyed but wasn't!" << endl;
		return 1;
	}































	pool.release(conn3);
	pool.release(conn4);
	pool.shrink();
	if (!pool.empty()) {
		cerr << "Shrunken pool is not empty!" << endl;
		return 1;
	}





	return 0;
}








Changes to bootstrap.

1
2
3

4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
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
56
57
58
59
60
61

62
63
64
65
66
67
68
69
70
71
72
73
74
75


76
77
78
79
80
81
82
83
84
85
86
87
88
89


90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119











#!/bin/bash

ARGS=1

BF_OPTIONS=
MAINT_FLAGS="--cache-file=config.cache"
while [ $ARGS != 0 ]
do
	case "$1" in
		bat)
			cmd /c bootstrap.bat $BF_OPTIONS
			exit 0
			;;

		nodoc)
			BF_OPTIONS="-DBUILDDOCS=no $BF_OPTIONS"
			shift
			;;

		noex)
			BF_OPTIONS="-DBUILDEXAMPLES=no $BF_OPTIONS"
			shift
			;;

		nolib)
			BF_OPTIONS="-DBUILDLIBRARY=no $BF_OPTIONS"
			shift
			;;

		nomaint)

			MAINT_FLAGS=
			shift
			;;

		noopt)
			export CXXFLAGS="-g -O0"
			shift
			;;

		pedantic)
			export CXXFLAGS="-g -O2 -ansi -pedantic -Wall -Wextra -W -Wold-style-cast -Wfloat-equal -Wwrite-strings -Wno-overloaded-virtual -Wno-long-long -Wno-variadic-macros -D_GLIBCXX_DEBUG -D_GLIBCXX_DEBUG_PEDANTIC"
			shift
			;;

		*)
			ARGS=0
			;;
	esac


done

# Check for existence of needed tools, so we can give a better error
# message than the shell will.
tools="make"											# POSIX
tools="$tools aclocal autoconf autoheader libtoolize"	# autotools
tools="$tools bakefile bakefilize bakefile_gen"			# Bakefile
for tool in $tools
do
	if ! type -p $tool > /dev/null
	then
		echo "FAILED to find build tool '$tool'!"
		echo
		echo BOOTSTRAP FAILED!

		echo
		exit 1
	fi
done

# Find location of Bakefile's stock M4 autoconf macros
for d in /usr/share/aclocal /usr/local/share/aclocal \
	'/c/Program Files (x86)/Bakefile/autoconf'
do
	BAKEFILE_M4="$d"
	if [ -e "$BAKEFILE_M4/bakefile.m4" ] ; then break ; fi
done
if [ ! -e "$BAKEFILE_M4/bakefile.m4" ]
then


	echo
	echo "Failed to find bakefile.m4.  Add the directory containing"
	echo "this to the bootstrap script."
	echo
	exit 1
fi

# Do Bakefile stuff first.  Autoconf can't succeed without
# autoconf_in.m4, which Bakefile creates.
success=
set -x &&
	for d in 3 5 8 ; do mkdir -p vc200$d ; done &&
	bakefilize &&
	rm -f INSTALL &&


	bakefile_gen $BF_OPTIONS &&
	bakefile -f gnu -o Makefile.simple -DBUILDLIBRARY=no mysql++.bkl &&
	set +x &&
	success=shonuff

# Do the autotools stuff if Bakefile steps succeeded
if [ -n "$success" ]
then
	rm -f config.cache
	mv autoconf_inc.m4 config > /dev/null 2>&1	# don't care if it fails
	set -x &&
		aclocal -I config -I "$BAKEFILE_M4" &&
		libtoolize &&
		autoheader &&
		autoconf &&
		./configure $MAINT_FLAGS $* &&
		make lib/querydef.h lib/ssqls.h &&
		set +x &&
		success=awyeah
fi

# Detect failure in any part of above
if [ -z "$success" ]
then
	echo
    echo BOOTSTRAP FAILED!
    echo
    exit 1
fi












|
|
<
>
|
<
<
<
<
<
<
|
<
|
|
<
|
<
|
<
<
<
<

|
<
|
<
|
|
>
<
<
<

<
<
|
<
|
|
<
|
<

<
<
<
|
>
>
|

<
<
<
<
<
<
<
<
<
<
|
|
>
|
<
<
|

<
<
<
|
<
<
<
<
<
>
>
|
<
<
|
<
|

<
<
<
<
<
<
<
>
>
<
<
<
<

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

<
<
<
<
<
<
<
<
|
>
>
>
>
>
>
>
>
>
>
>
1
2

3
4






5

6
7

8

9




10
11

12

13
14
15



16


17

18
19

20

21



22
23
24
25
26










27
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
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE article PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"

                         "http://www.docbook.org/xml/4.2/docbookx.dtd"
[ <!ENTITY % xinclude SYSTEM "xinclude.mod">






%xinclude;

]>
<article>

	<articleinfo>

		<title>MySQL++ v3.2.1 User Manual</title>





		<authorgroup>

			<author>

				<firstname>Kevin</firstname>
				<surname>Atkinson</surname>
			</author>






			<author>

				<firstname>Sinisa</firstname>
				<surname>Milivojevic</surname>

			</author>





			<author>
				<firstname>Monty</firstname>
				<surname>Widenius</surname>
			</author>











			<author>
				<firstname>Warren</firstname>
				<surname>Young</surname>
			</author>


		</authorgroup>




		<copyright>





			<year>1998-2001, 2005-2010</year>
			<holder>Kevin Atkinson (original author)</holder>
			<holder>MySQL AB</holder>


			<holder>Educational Technology Resources</holder>

		</copyright>








		<pubdate><?dbtimestamp format="B d, Y"?></pubdate>
	</articleinfo>





























	<xi:include href="intro.dbx" xmlns:xi="http://www.w3.org/2001/XInclude"/>
	<xi:include href="overview.dbx" xmlns:xi="http://www.w3.org/2001/XInclude"/>
	<xi:include href="tutorial.dbx" xmlns:xi="http://www.w3.org/2001/XInclude"/>
	<xi:include href="tquery.dbx" xmlns:xi="http://www.w3.org/2001/XInclude"/>
	<xi:include href="ssqls.dbx" xmlns:xi="http://www.w3.org/2001/XInclude"/>
	<xi:include href="unicode.dbx" xmlns:xi="http://www.w3.org/2001/XInclude"/>
	<xi:include href="threads.dbx" xmlns:xi="http://www.w3.org/2001/XInclude"/>
	<xi:include href="configuration.dbx" xmlns:xi="http://www.w3.org/2001/XInclude"/>
	<xi:include href="incorporating.dbx" xmlns:xi="http://www.w3.org/2001/XInclude"/>
	<xi:include href="breakages.dbx" xmlns:xi="http://www.w3.org/2001/XInclude"/>
	<xi:include href="licenses.dbx" xmlns:xi="http://www.w3.org/2001/XInclude"/>
</article>

Changes to bootstrap.bat.

1

2
3
4
5


6
7
8
9
10
11
12
13
14

15



16
17
18





19


20

21


22

23


24
25
26
27
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
56
57
58
59
60
61
62
63


@echo off

if not exist vc2003 mkdir vc2003
if not exist vc2005 mkdir vc2005
if not exist vc2008 mkdir vc2008



bakefile_gen %*
if errorlevel 1 exit
if not exist vc2003\mysql++.sln goto no_bakefile
if not exist vc2005\mysql++.sln goto no_bakefile
if not exist vc2008\mysql++.sln goto no_bakefile

cd lib
perl querydef.pl
if errorlevel 1 exit

if not exist querydef.h goto no_perl



perl ssqls.pl
if errorlevel 1 exit
if not exist ssqls.h goto no_perl








if not exist mysql++.h goto no_mysqlpp_h

cd ..




exit



:no_bakefile
echo.
echo Bakefile doesn't seem to be installed on this system.  Download it
echo from http://bakefile.org/  You need version 0.2.3 or newer.
echo.
exit




:no_perl
echo.
echo You need a Perl interpreter installed on your system, somewhere in
echo the PATH.  Any recent version or flavor should work; we don't use
echo any special extensions.  The easiest to install on Windows would be
echo ActivePerl, from http://activestate.com/Products/activeperl/
echo If you're familiar with Unix, you might like Cygwin better instead:
echo http://cygwin.com/setup.exe

echo.

cd ..







exit









:no_mysqlpp_h

echo.
echo WARNING: Can't make lib/mysql++.h

echo.

echo On Unixy systems, autoconf creates lib/mysql++.h from lib/mysql++.h.in
echo but there is no easy way to do this on Windows.  You can do it manually:
echo just copy the file to the new name, and edit the MYSQLPP_HEADER_VERSION
echo definition to put the proper version number parts into the macro.  It
echo needs to look something like this:
echo.
echo #define MYSQLPP_HEADER_VERSION MYSQLPP_VERSION(3, 0, 0)

echo.
echo It's important that the three numbers match the actual library version
echo number, or else programs that check this (like resetdb) will fail.
echo.
echo Alternately, if you've also got MySQL++ installed on some Unixy type
echo system, you can let its bootstrap procedure create mysql++.h and then
echo copy it to the Windows machine.
echo.
cd ..


<
>
|
|
<

>
>
|
<
|
|
|

|
|
|
>
|
>
>
>
|
|
<
>
>
>
>
>

>
>
|
>
|
>
>

>
|
>
>
|
<
<
<
|
<
<
>
>
>
|
|
|
<
<
|
|
|
|
>
|
>
|
>
>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
|
<
>
|
<
>
|
>
|
<
<
<
<
|
<
>
|
<
<
<
<
<
|
|
<
>
>

1
2
3

4
5
6
7

8
9
10
11
12
13
14
15
16
17
18
19
20
21

22
23
24
25
26
27
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
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72

73
74

75
76
77
78




79

80
81





82
83

84
85

/***********************************************************************
 simple2.cpp - Retrieves the entire contents of the sample stock table
	using a "store" query, and prints it out.


 Copyright (c) 1998 by Kevin Atkinson, (c) 1999-2001 by MySQL AB, and
 (c) 2004-2007 by Educational Technology Resources, Inc.  Others may
 also hold copyrights on code in this file.  See the CREDITS.txt file

 in the top directory of the distribution for details.

 This file is part of MySQL++.

 MySQL++ is free software; you can redistribute it and/or modify it
 under the terms of the GNU Lesser General Public License as published
 by the Free Software Foundation; either version 2.1 of the License, or
 (at your option) any later version.

 MySQL++ is distributed in the hope that it will be useful, but WITHOUT
 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
 License for more details.


 You should have received a copy of the GNU Lesser General Public
 License along with MySQL++; if not, write to the Free Software
 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
 USA
***********************************************************************/

#include "cmdline.h"
#include "printdata.h"

#include <mysql++.h>

#include <iostream>
#include <iomanip>

using namespace std;

int
main(int argc, char *argv[])
{



	// Get database access parameters from command line


	const char* db = 0, *server = 0, *user = 0, *pass = "";
	if (!parse_command_line(argc, argv, &db, &server, &user, &pass)) {
		return 1;
	}

	// Connect to the sample database.


	mysqlpp::Connection conn(false);
	if (conn.connect(db, server, user, pass)) {
		// Retrieve the sample stock table set up by resetdb
		mysqlpp::Query query = conn.query("select * from stock");
		mysqlpp::StoreQueryResult res = query.store();

		// Display results
		if (res) {
			// Display header
			cout.setf(ios::left);
			cout << setw(31) << "Item" <<
					setw(10) << "Num" <<
					setw(10) << "Weight" <<
					setw(10) << "Price" <<
					"Date" << endl << endl;

			// Get each row in result set, and print its contents
			for (size_t i = 0; i < res.num_rows(); ++i) {
				cout << setw(30) << res[i]["item"] << ' ' <<
						setw(9) << res[i]["num"] << ' ' <<
						setw(9) << res[i]["weight"] << ' ' <<
						setw(9) << res[i]["price"] << ' ' <<
						setw(9) << res[i]["sdate"] <<
						endl;
			}

		}
		else {

			cerr << "Failed to get stock table: " << query.error() << endl;
			return 1;
		}





		return 0;

	}
	else {





		cerr << "DB connection failed: " << conn.error() << endl;
		return 1;

	}
}

Changes to cleanmf.

more than 10,000 changes

Changes to config/acx_pthread.m4.

1
2


3
4
5
6
7
8
9


10
11
12
13

14
15

16
17
18
19

20
21
22
23
24
25
26
27
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

56
57
58
59
60

61
62
63
64
65
66
67
68

69
70
71
72
73
74
75
76

77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92

93
94
95
96
97
98
99
100
101
102

103
104

105

106



107

108

109




110
111
112
113
114

115
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
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
191
192
193
194
195
196
197
198
199
200
201
202

203
204
205

206
207
208
209
210
211
212

213
214
215
216
217
218
219
220
221
222
223

224
225
226
227
228
229
230
231
232
233
234


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
269
270
271
272
273
274
275
# ===========================================================================
#              http://autoconf-archive.cryp.to/acx_pthread.html


# ===========================================================================
#
# SYNOPSIS
#
#   ACX_PTHREAD([ACTION-IF-FOUND[, ACTION-IF-NOT-FOUND]])
#
# DESCRIPTION


#
#   This macro figures out how to build C programs using POSIX threads. It
#   sets the PTHREAD_LIBS output variable to the threads library and linker
#   flags, and the PTHREAD_CFLAGS output variable to any special C compiler

#   flags that are needed. (The user can also force certain compiler
#   flags/libs to be tested by setting these environment variables.)

#
#   Also sets PTHREAD_CC to any special C compiler that is needed for
#   multi-threaded programs (defaults to the value of CC otherwise). (This
#   is necessary on AIX to use the special cc_r compiler alias.)

#
#   NOTE: You are assumed to not only compile your program with these flags,
#   but also link it with them as well. e.g. you should link with
#   $PTHREAD_CC $CFLAGS $PTHREAD_CFLAGS $LDFLAGS ... $PTHREAD_LIBS $LIBS
#
#   If you are only building threads programs, you may wish to use these
#   variables in your default LIBS, CFLAGS, and CC:
#
#          LIBS="$PTHREAD_LIBS $LIBS"
#          CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
#          CC="$PTHREAD_CC"
#


#   In addition, if the PTHREAD_CREATE_JOINABLE thread-attribute constant
#   has a nonstandard name, defines PTHREAD_CREATE_JOINABLE to that name
#   (e.g. PTHREAD_CREATE_UNDETACHED on AIX).
#
#   ACTION-IF-FOUND is a list of shell commands to run if a threads library
#   is found, and ACTION-IF-NOT-FOUND is a list of commands to run it if it
#   is not found. If ACTION-IF-FOUND is not specified, the default action
#   will define HAVE_PTHREAD.
#



#   Please let the authors know if this macro fails on any platform, or if
#   you have any other suggestions or comments. This macro was based on work
#   by SGJ on autoconf scripts for FFTW (http://www.fftw.org/) (with help
#   from M. Frigo), as well as ac_pthread and hb_pthread macros posted by
#   Alejandro Forero Cuervo to the autoconf macro repository. We are also
#   grateful for the helpful feedback of numerous users.
#

# LAST MODIFICATION
#
#   2008-04-12
#



# COPYLEFT
#
#   Copyright (c) 2008 Steven G. Johnson <stevenj@alum.mit.edu>
#

#   This program is free software: you can redistribute it and/or modify it
#   under the terms of the GNU General Public License as published by the
#   Free Software Foundation, either version 3 of the License, or (at your
#   option) any later version.
#

#   This program is distributed in the hope that it will be useful, but
#   WITHOUT ANY WARRANTY; without even the implied warranty of
#   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
#   Public License for more details.
#
#   You should have received a copy of the GNU General Public License along
#   with this program. If not, see <http://www.gnu.org/licenses/>.
#

#   As a special exception, the respective Autoconf Macro's copyright owner
#   gives unlimited permission to copy, distribute and modify the configure
#   scripts that are the output of Autoconf when processing the Macro. You
#   need not follow the terms of the GNU General Public License when using
#   or distributing such scripts, even though portions of the text of the
#   Macro appear in them. The GNU General Public License (GPL) does govern
#   all other use of the material that constitutes the Autoconf Macro.
#

#   This special exception to the GPL applies to versions of the Autoconf
#   Macro released by the Autoconf Macro Archive. When you make and
#   distribute a modified version of the Autoconf Macro, you may extend this
#   special exception to the GPL to apply to your modified version as well.

AC_DEFUN([ACX_PTHREAD], [
AC_REQUIRE([AC_CANONICAL_HOST])
AC_LANG_SAVE
AC_LANG_C
acx_pthread_ok=no

# We used to check for pthread.h first, but this fails if pthread.h
# requires special compiler flags (e.g. on True64 or Sequent).
# It gets checked for in the link test anyway.

# First of all, check if the user has set any of the PTHREAD_LIBS,

# etcetera environment variables, and if threads linking works using
# them:
if test x"$PTHREAD_LIBS$PTHREAD_CFLAGS" != x; then
        save_CFLAGS="$CFLAGS"
        CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
        save_LIBS="$LIBS"
        LIBS="$PTHREAD_LIBS $LIBS"
        AC_MSG_CHECKING([for pthread_join in LIBS=$PTHREAD_LIBS with CFLAGS=$PTHREAD_CFLAGS])
        AC_TRY_LINK_FUNC(pthread_join, acx_pthread_ok=yes)
        AC_MSG_RESULT($acx_pthread_ok)

        if test x"$acx_pthread_ok" = xno; then
                PTHREAD_LIBS=""

                PTHREAD_CFLAGS=""

        fi



        LIBS="$save_LIBS"

        CFLAGS="$save_CFLAGS"

fi





# We must check for the threads library under a number of different
# names; the ordering is very important because some systems
# (e.g. DEC) have both -lpthread and -lpthreads, where one of the
# libraries is broken (non-POSIX).


# Create a list of thread flags to try.  Items starting with a "-" are
# C compiler flags, and other items are library names, except for "none"
# which indicates that we try without any flags at all, and "pthread-config"
# which is a program returning the flags for the Pth emulation library.







acx_pthread_flags="pthreads none -Kthread -kthread lthread -pthread -pthreads -mthreads pthread --thread-safe -mt pthread-config"

# The ordering *is* (sometimes) important.  Some notes on the
# individual items follow:

# pthreads: AIX (must check this before -lpthread)
# none: in case threads are in libc; should be tried before -Kthread and
#       other compiler flags to prevent continual compiler warnings
# -Kthread: Sequent (threads in libc, but -Kthread needed for pthread.h)
# -kthread: FreeBSD kernel threads (preferred to -pthread since SMP-able)
# lthread: LinuxThreads port on FreeBSD (also preferred to -pthread)
# -pthread: Linux/gcc (kernel threads), BSD/gcc (userland threads)
# -pthreads: Solaris/gcc
# -mthreads: Mingw32/gcc, Lynx/gcc
# -mt: Sun Workshop C (may only link SunOS threads [-lthread], but it
#      doesn't hurt to check since this sometimes defines pthreads too;
#      also defines -D_REENTRANT)
#      ... -mt is also the pthreads flag for HP/aCC
# pthread: Linux, etcetera
# --thread-safe: KAI C++
# pthread-config: use pthread-config program (for GNU Pth library)





case "${host_cpu}-${host_os}" in
        *solaris*)

        # On Solaris (at least, for some versions), libc contains stubbed
        # (non-functional) versions of the pthreads routines, so link-based
        # tests will erroneously succeed.  (We need to link with -pthreads/-mt/
        # -lpthread.)  (The stubs are missing pthread_cleanup_push, or rather







        # a function called by this macro, so we could check for that, but
        # who knows whether they'll stub that too in a future libc.)  So,

        # we'll just look for -pthreads and -lpthread first:


        acx_pthread_flags="-pthreads pthread -mt -pthread $acx_pthread_flags"
        ;;



esac

if test x"$acx_pthread_ok" = xno; then
for flag in $acx_pthread_flags; do



        case $flag in
                none)
                AC_MSG_CHECKING([whether pthreads work without any flags])
                ;;



                -*)
                AC_MSG_CHECKING([whether pthreads work with $flag])
                PTHREAD_CFLAGS="$flag"
                ;;



		pthread-config)
		AC_CHECK_PROG(acx_pthread_config, pthread-config, yes, no)
		if test x"$acx_pthread_config" = xno; then continue; fi
		PTHREAD_CFLAGS="`pthread-config --cflags`"
		PTHREAD_LIBS="`pthread-config --ldflags` `pthread-config --libs`"
		;;


                *)
                AC_MSG_CHECKING([for the pthreads library -l$flag])
                PTHREAD_LIBS="-l$flag"
                ;;

        esac

        save_LIBS="$LIBS"
        save_CFLAGS="$CFLAGS"
        LIBS="$PTHREAD_LIBS $LIBS"
        CFLAGS="$CFLAGS $PTHREAD_CFLAGS"


        # Check for various functions.  We must include pthread.h,
        # since some functions may be macros.  (On the Sequent, we
        # need a special flag -Kthread to make this header compile.)
        # We check for pthread_join because it is in -lpthread on IRIX
        # while pthread_create is in libc.  We check for pthread_attr_init
        # due to DEC craziness with -lpthreads.  We check for
        # pthread_cleanup_push because it is one of the few pthread
        # functions on Solaris that doesn't have a non-functional libc stub.
        # We try pthread_create on general principles.
        AC_TRY_LINK([#include <pthread.h>],
                    [pthread_t th; pthread_join(th, 0);
                     pthread_attr_init(0); pthread_cleanup_push(0, 0);
                     pthread_create(0,0,0,0); pthread_cleanup_pop(0); ],
                    [acx_pthread_ok=yes])


        LIBS="$save_LIBS"
        CFLAGS="$save_CFLAGS"


        AC_MSG_RESULT($acx_pthread_ok)
        if test "x$acx_pthread_ok" = xyes; then
                break;
        fi

        PTHREAD_LIBS=""

        PTHREAD_CFLAGS=""
done
fi

# Various other checks:
if test "x$acx_pthread_ok" = xyes; then
        save_LIBS="$LIBS"
        LIBS="$PTHREAD_LIBS $LIBS"
        save_CFLAGS="$CFLAGS"
        CFLAGS="$CFLAGS $PTHREAD_CFLAGS"


        # Detect AIX lossage: JOINABLE attribute is called UNDETACHED.
	AC_MSG_CHECKING([for joinable pthread attribute])
	attr_name=unknown
	for attr in PTHREAD_CREATE_JOINABLE PTHREAD_CREATE_UNDETACHED; do
	    AC_TRY_LINK([#include <pthread.h>], [int attr=$attr; return attr;],
                        [attr_name=$attr; break])
	done
        AC_MSG_RESULT($attr_name)
        if test "$attr_name" != PTHREAD_CREATE_JOINABLE; then
            AC_DEFINE_UNQUOTED(PTHREAD_CREATE_JOINABLE, $attr_name,
                               [Define to necessary symbol if this constant


                                uses a non-standard name on your system.])


        fi



        AC_MSG_CHECKING([if more special flags are required for pthreads])
        flag=no
        case "${host_cpu}-${host_os}" in
            *-aix* | *-freebsd* | *-darwin*) flag="-D_THREAD_SAFE";;
            *solaris* | *-osf* | *-hpux*) flag="-D_REENTRANT";;
        esac
        AC_MSG_RESULT(${flag})
        if test "x$flag" != xno; then
            PTHREAD_CFLAGS="$flag $PTHREAD_CFLAGS"
        fi

        LIBS="$save_LIBS"

        CFLAGS="$save_CFLAGS"


        # More AIX lossage: must compile with xlc_r or cc_r
	if test x"$GCC" != xyes; then
          AC_CHECK_PROGS(PTHREAD_CC, xlc_r cc_r, ${CC})
        else

          PTHREAD_CC=$CC
	fi

else


        PTHREAD_CC="$CC"
fi


AC_SUBST(PTHREAD_LIBS)

AC_SUBST(PTHREAD_CFLAGS)
AC_SUBST(PTHREAD_CC)


# Finally, execute ACTION-IF-FOUND/ACTION-IF-NOT-FOUND:
if test x"$acx_pthread_ok" = xyes; then
        ifelse([$1],,AC_DEFINE(HAVE_PTHREAD,1,[Define if you have POSIX threads libraries and header files.]),[$1])
        :
else
        acx_pthread_ok=no
        $2
fi
AC_LANG_RESTORE
])dnl ACX_PTHREAD
|
|
>
>
|
|
<
|
<
|
|
>
>
|
<
<
|
>
|
|
>
|
<
<
|
>
|
|
<
|
|
|
|
|
|
<
<
|
>
>
|
<
<
|
|
<
<
<
|
>
>
>
|
|
|
|
|
|
<
>
|
<
|
<
>
>
>
|
<
|
<
>
|
|
|
|
<
>
|
|
|
|
<
<
<
<
>
|
|
|
|
|
|
|
<
>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
>
|
<
|
|
|
<
<
<
<
|
>
|
|
>
|
>
|
>
>
>
|
>
|
>
|
>
>
>
>

<
<
<
<
>

<
<
<
<
>
>
>
>
>
>

<

<
|

<
<
<
<
<
<
<
<
|
<
<
<
<
<
<
<

>
>
>
>
|
|
|
|
|
|
|
>
>
>
>
>
>
>
|
<
>
|
>

<
<
>
>
>
|

<
<
>
>

<
<
<
<
>
>

<
<
<
<
>
>

<
|
|
|
|
<
>

|
|
|
<
>
|

|
|
|
|
>

<
|
|
|
|
|
|
|
|
|
|
|
|
|
>

<
|
>

<
|
|
<

|
>
|
|
|

|
|
|
|
|
<

>
|
|
|
|
|
|
|
|
|
|
|
>
>
|
>
>
|
>
>

<
|
|
|
|
|
|
|
|
<

<
>
|

>
|
|
<
|
>
|
|
>
|
>
>
|
|
>

<
>
|
|
>

<
<
<
|
<
|
<
|
<
<
1
2
3
4
5
6

7

8
9
10
11
12


13
14
15
16
17
18


19
20
21
22

23
24
25
26
27
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
56
57

58
59
60
61
62




63
64
65
66
67
68
69
70

71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89

90
91
92




93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113




114
115




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
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
191
192
193
194
195
196
197

198
199
200

201
202

203
204
205
206
207
208
209
210
211
212
213
214

215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
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



269

270

271


# =========================================================================
#     This makefile was generated by
#     Bakefile 0.2.0 (http://bakefile.sourceforge.net)
#     Do not modify, all changes will be overwritten!
# =========================================================================





# -------------------------------------------------------------------------
# These are configurable options:
# -------------------------------------------------------------------------



# C++ compiler 
CXX = g++

# Standard flags for C++ 
CXXFLAGS = 



# Standard preprocessor flags (common for CC and CXX) 
CPPFLAGS = 

# Standard linker flags 

LDFLAGS = 

# Type of compiled binaries [debug,release]
BUILD = debug





# -------------------------------------------------------------------------
# Do not modify the rest of this file!
# -------------------------------------------------------------------------



### Variables: ###




CPPDEPS = -MT$@ -MF$@.d -MD
UTIL_CXXFLAGS = -mthreads $(__DEBUGINFO) -I..\lib -D_UNICODE -Ic:\mysql\include \
	-DMYSQLPP_NO_DLL $(CPPFLAGS) $(CXXFLAGS)
UTIL_OBJECTS =  \
	util_util.o
RESETDB_CXXFLAGS = -mthreads $(__DEBUGINFO) -I..\lib -D_UNICODE \
	-Ic:\mysql\include -DMYSQLPP_NO_DLL $(CPPFLAGS) $(CXXFLAGS)
RESETDB_OBJECTS =  \
	resetdb_resetdb.o

SIMPLE1_CXXFLAGS = -mthreads $(__DEBUGINFO) -I..\lib -D_UNICODE \
	-Ic:\mysql\include -DMYSQLPP_NO_DLL $(CPPFLAGS) $(CXXFLAGS)

SIMPLE1_OBJECTS =  \

	simple1_simple1.o
SIMPLE2_CXXFLAGS = -mthreads $(__DEBUGINFO) -I..\lib -D_UNICODE \
	-Ic:\mysql\include -DMYSQLPP_NO_DLL $(CPPFLAGS) $(CXXFLAGS)
SIMPLE2_OBJECTS =  \

	simple2_simple2.o

SIMPLE3_CXXFLAGS = -mthreads $(__DEBUGINFO) -I..\lib -D_UNICODE \
	-Ic:\mysql\include -DMYSQLPP_NO_DLL $(CPPFLAGS) $(CXXFLAGS)
SIMPLE3_OBJECTS =  \
	simple3_simple3.o
USEQUERY_CXXFLAGS = -mthreads $(__DEBUGINFO) -I..\lib -D_UNICODE \

	-Ic:\mysql\include -DMYSQLPP_NO_DLL $(CPPFLAGS) $(CXXFLAGS)
USEQUERY_OBJECTS =  \
	usequery_usequery.o
MULTIQUERY_CXXFLAGS = -mthreads $(__DEBUGINFO) -I..\lib -D_UNICODE \
	-Ic:\mysql\include -DMYSQLPP_NO_DLL $(CPPFLAGS) $(CXXFLAGS)




MULTIQUERY_OBJECTS =  \
	multiquery_multiquery.o
CUSTOM1_CXXFLAGS = -mthreads $(__DEBUGINFO) -I..\lib -D_UNICODE \
	-Ic:\mysql\include -DMYSQLPP_NO_DLL $(CPPFLAGS) $(CXXFLAGS)
CUSTOM1_OBJECTS =  \
	custom1_custom1.o
CUSTOM2_CXXFLAGS = -mthreads $(__DEBUGINFO) -I..\lib -D_UNICODE \
	-Ic:\mysql\include -DMYSQLPP_NO_DLL $(CPPFLAGS) $(CXXFLAGS)

CUSTOM2_OBJECTS =  \
	custom2_custom2.o
CUSTOM3_CXXFLAGS = -mthreads $(__DEBUGINFO) -I..\lib -D_UNICODE \
	-Ic:\mysql\include -DMYSQLPP_NO_DLL $(CPPFLAGS) $(CXXFLAGS)
CUSTOM3_OBJECTS =  \
	custom3_custom3.o
CUSTOM4_CXXFLAGS = -mthreads $(__DEBUGINFO) -I..\lib -D_UNICODE \
	-Ic:\mysql\include -DMYSQLPP_NO_DLL $(CPPFLAGS) $(CXXFLAGS)
CUSTOM4_OBJECTS =  \
	custom4_custom4.o
CUSTOM5_CXXFLAGS = -mthreads $(__DEBUGINFO) -I..\lib -D_UNICODE \
	-Ic:\mysql\include -DMYSQLPP_NO_DLL $(CPPFLAGS) $(CXXFLAGS)
CUSTOM5_OBJECTS =  \
	custom5_custom5.o
CUSTOM6_CXXFLAGS = -mthreads $(__DEBUGINFO) -I..\lib -D_UNICODE \
	-Ic:\mysql\include -DMYSQLPP_NO_DLL $(CPPFLAGS) $(CXXFLAGS)
CUSTOM6_OBJECTS =  \
	custom6_custom6.o
DBINFO_CXXFLAGS = -mthreads $(__DEBUGINFO) -I..\lib -D_UNICODE \

	-Ic:\mysql\include -DMYSQLPP_NO_DLL $(CPPFLAGS) $(CXXFLAGS)
DBINFO_OBJECTS =  \
	dbinfo_dbinfo.o




FIELDINF1_CXXFLAGS = -mthreads $(__DEBUGINFO) -I..\lib -D_UNICODE \
	-Ic:\mysql\include -DMYSQLPP_NO_DLL $(CPPFLAGS) $(CXXFLAGS)
FIELDINF1_OBJECTS =  \
	fieldinf1_fieldinf1.o
XACTION_CXXFLAGS = -mthreads $(__DEBUGINFO) -I..\lib -D_UNICODE \
	-Ic:\mysql\include -DMYSQLPP_NO_DLL $(CPPFLAGS) $(CXXFLAGS)
XACTION_OBJECTS =  \
	xaction_xaction.o
CGI_IMAGE_CXXFLAGS = -mthreads $(__DEBUGINFO) -I..\lib -D_UNICODE \
	-Ic:\mysql\include -DMYSQLPP_NO_DLL $(CPPFLAGS) $(CXXFLAGS)
CGI_IMAGE_OBJECTS =  \
	cgi_image_cgi_image.o
LOAD_FILE_CXXFLAGS = -mthreads $(__DEBUGINFO) -I..\lib -D_UNICODE \
	-Ic:\mysql\include -DMYSQLPP_NO_DLL $(CPPFLAGS) $(CXXFLAGS)
LOAD_FILE_OBJECTS =  \
	load_file_load_file.o
UPDEL_CXXFLAGS = -mthreads $(__DEBUGINFO) -I..\lib -D_UNICODE -Ic:\mysql\include \
	-DMYSQLPP_NO_DLL $(CPPFLAGS) $(CXXFLAGS)
UPDEL_OBJECTS =  \
	updel_updel.o





### Conditionally set variables: ###





ifeq ($(BUILD),debug)
__DEBUGINFO = -g
endif
ifeq ($(BUILD),release)
__DEBUGINFO = 
endif




### Targets: ###









all: libmysqlpp_util.a resetdb.exe simple1.exe simple2.exe simple3.exe usequery.exe multiquery.exe custom1.exe custom2.exe custom3.exe custom4.exe custom5.exe custom6.exe dbinfo.exe fieldinf1.exe xaction.exe cgi_image.exe load_file.exe updel.exe








clean: 
	-if exist .\*.o del .\*.o
	-if exist .\*.d del .\*.d
	-if exist libmysqlpp_util.a del libmysqlpp_util.a
	-if exist resetdb.exe del resetdb.exe
	-if exist simple1.exe del simple1.exe
	-if exist simple2.exe del simple2.exe
	-if exist simple3.exe del simple3.exe
	-if exist usequery.exe del usequery.exe
	-if exist multiquery.exe del multiquery.exe
	-if exist custom1.exe del custom1.exe
	-if exist custom2.exe del custom2.exe
	-if exist custom3.exe del custom3.exe
	-if exist custom4.exe del custom4.exe
	-if exist custom5.exe del custom5.exe
	-if exist custom6.exe del custom6.exe
	-if exist dbinfo.exe del dbinfo.exe
	-if exist fieldinf1.exe del fieldinf1.exe
	-if exist xaction.exe del xaction.exe

	-if exist cgi_image.exe del cgi_image.exe
	-if exist load_file.exe del load_file.exe
	-if exist updel.exe del updel.exe



libmysqlpp_util.a: $(UTIL_OBJECTS)
	if exist $@ del $@
	ar rcu $@ $(UTIL_OBJECTS)
	ranlib $@



resetdb.exe: $(RESETDB_OBJECTS) libmysqlpp_util.a
	$(CXX) -o $@ $(RESETDB_OBJECTS) $(LDFLAGS) -L. -mthreads $(__DEBUGINFO) -Lc:\mysql\lib\opt -Wl,--enable-auto-import -L..\lib  -lmysqlpp_util -lmysqlpp -lmysqlclient





simple1.exe: $(SIMPLE1_OBJECTS) libmysqlpp_util.a
	$(CXX) -o $@ $(SIMPLE1_OBJECTS) $(LDFLAGS) -L. -mthreads $(__DEBUGINFO) -Lc:\mysql\lib\opt -Wl,--enable-auto-import -L..\lib  -lmysqlpp_util -lmysqlpp -lmysqlclient





simple2.exe: $(SIMPLE2_OBJECTS) libmysqlpp_util.a
	$(CXX) -o $@ $(SIMPLE2_OBJECTS) $(LDFLAGS) -L. -mthreads $(__DEBUGINFO) -Lc:\mysql\lib\opt -Wl,--enable-auto-import -L..\lib  -lmysqlpp_util -lmysqlpp -lmysqlclient


simple3.exe: $(SIMPLE3_OBJECTS) libmysqlpp_util.a
	$(CXX) -o $@ $(SIMPLE3_OBJECTS) $(LDFLAGS) -L. -mthreads $(__DEBUGINFO) -Lc:\mysql\lib\opt -Wl,--enable-auto-import -L..\lib  -lmysqlpp_util -lmysqlpp -lmysqlclient

usequery.exe: $(USEQUERY_OBJECTS) libmysqlpp_util.a

	$(CXX) -o $@ $(USEQUERY_OBJECTS) $(LDFLAGS) -L. -mthreads $(__DEBUGINFO) -Lc:\mysql\lib\opt -Wl,--enable-auto-import -L..\lib  -lmysqlpp_util -lmysqlpp -lmysqlclient

multiquery.exe: $(MULTIQUERY_OBJECTS) libmysqlpp_util.a
	$(CXX) -o $@ $(MULTIQUERY_OBJECTS) $(LDFLAGS) -L. -mthreads $(__DEBUGINFO) -Lc:\mysql\lib\opt -Wl,--enable-auto-import -L..\lib  -lmysqlpp_util -lmysqlpp -lmysqlclient


custom1.exe: $(CUSTOM1_OBJECTS) libmysqlpp_util.a
	$(CXX) -o $@ $(CUSTOM1_OBJECTS) $(LDFLAGS) -L. -mthreads $(__DEBUGINFO) -Lc:\mysql\lib\opt -Wl,--enable-auto-import -L..\lib  -lmysqlpp_util -lmysqlpp -lmysqlclient

custom2.exe: $(CUSTOM2_OBJECTS) libmysqlpp_util.a
	$(CXX) -o $@ $(CUSTOM2_OBJECTS) $(LDFLAGS) -L. -mthreads $(__DEBUGINFO) -Lc:\mysql\lib\opt -Wl,--enable-auto-import -L..\lib  -lmysqlpp_util -lmysqlpp -lmysqlclient

custom3.exe: $(CUSTOM3_OBJECTS) libmysqlpp_util.a
	$(CXX) -o $@ $(CUSTOM3_OBJECTS) $(LDFLAGS) -L. -mthreads $(__DEBUGINFO) -Lc:\mysql\lib\opt -Wl,--enable-auto-import -L..\lib  -lmysqlpp_util -lmysqlpp -lmysqlclient


custom4.exe: $(CUSTOM4_OBJECTS) libmysqlpp_util.a
	$(CXX) -o $@ $(CUSTOM4_OBJECTS) $(LDFLAGS) -L. -mthreads $(__DEBUGINFO) -Lc:\mysql\lib\opt -Wl,--enable-auto-import -L..\lib  -lmysqlpp_util -lmysqlpp -lmysqlclient

custom5.exe: $(CUSTOM5_OBJECTS) libmysqlpp_util.a
	$(CXX) -o $@ $(CUSTOM5_OBJECTS) $(LDFLAGS) -L. -mthreads $(__DEBUGINFO) -Lc:\mysql\lib\opt -Wl,--enable-auto-import -L..\lib  -lmysqlpp_util -lmysqlpp -lmysqlclient

custom6.exe: $(CUSTOM6_OBJECTS) libmysqlpp_util.a
	$(CXX) -o $@ $(CUSTOM6_OBJECTS) $(LDFLAGS) -L. -mthreads $(__DEBUGINFO) -Lc:\mysql\lib\opt -Wl,--enable-auto-import -L..\lib  -lmysqlpp_util -lmysqlpp -lmysqlclient

dbinfo.exe: $(DBINFO_OBJECTS) libmysqlpp_util.a
	$(CXX) -o $@ $(DBINFO_OBJECTS) $(LDFLAGS) -L. -mthreads $(__DEBUGINFO) -Lc:\mysql\lib\opt -Wl,--enable-auto-import -L..\lib  -lmysqlpp_util -lmysqlpp -lmysqlclient

fieldinf1.exe: $(FIELDINF1_OBJECTS) libmysqlpp_util.a
	$(CXX) -o $@ $(FIELDINF1_OBJECTS) $(LDFLAGS) -L. -mthreads $(__DEBUGINFO) -Lc:\mysql\lib\opt -Wl,--enable-auto-import -L..\lib  -lmysqlpp_util -lmysqlpp -lmysqlclient


xaction.exe: $(XACTION_OBJECTS) libmysqlpp_util.a
	$(CXX) -o $@ $(XACTION_OBJECTS) $(LDFLAGS) -L. -mthreads $(__DEBUGINFO) -Lc:\mysql\lib\opt -Wl,--enable-auto-import -L..\lib  -lmysqlpp_util -lmysqlpp -lmysqlclient


cgi_image.exe: $(CGI_IMAGE_OBJECTS)
	$(CXX) -o $@ $(CGI_IMAGE_OBJECTS) $(LDFLAGS) -mthreads $(__DEBUGINFO) -Lc:\mysql\lib\opt -Wl,--enable-auto-import -L..\lib  -lmysqlpp -lmysqlclient


load_file.exe: $(LOAD_FILE_OBJECTS)
	$(CXX) -o $@ $(LOAD_FILE_OBJECTS) $(LDFLAGS) -mthreads $(__DEBUGINFO) -Lc:\mysql\lib\opt -Wl,--enable-auto-import -L..\lib  -lmysqlpp -lmysqlclient

updel.exe: $(UPDEL_OBJECTS)
	$(CXX) -o $@ $(UPDEL_OBJECTS) $(LDFLAGS) -mthreads $(__DEBUGINFO) -Lc:\mysql\lib\opt -Wl,--enable-auto-import -L..\lib  -lmysqlpp -lmysqlclient

util_util.o: ./util.cpp
	$(CXX) -c -o $@ $(UTIL_CXXFLAGS) $(CPPDEPS) $<

resetdb_resetdb.o: ./resetdb.cpp
	$(CXX) -c -o $@ $(RESETDB_CXXFLAGS) $(CPPDEPS) $<


simple1_simple1.o: ./simple1.cpp
	$(CXX) -c -o $@ $(SIMPLE1_CXXFLAGS) $(CPPDEPS) $<

simple2_simple2.o: ./simple2.cpp
	$(CXX) -c -o $@ $(SIMPLE2_CXXFLAGS) $(CPPDEPS) $<

simple3_simple3.o: ./simple3.cpp
	$(CXX) -c -o $@ $(SIMPLE3_CXXFLAGS) $(CPPDEPS) $<

usequery_usequery.o: ./usequery.cpp
	$(CXX) -c -o $@ $(USEQUERY_CXXFLAGS) $(CPPDEPS) $<

multiquery_multiquery.o: ./multiquery.cpp
	$(CXX) -c -o $@ $(MULTIQUERY_CXXFLAGS) $(CPPDEPS) $<

custom1_custom1.o: ./custom1.cpp
	$(CXX) -c -o $@ $(CUSTOM1_CXXFLAGS) $(CPPDEPS) $<

custom2_custom2.o: ./custom2.cpp
	$(CXX) -c -o $@ $(CUSTOM2_CXXFLAGS) $(CPPDEPS) $<


custom3_custom3.o: ./custom3.cpp
	$(CXX) -c -o $@ $(CUSTOM3_CXXFLAGS) $(CPPDEPS) $<

custom4_custom4.o: ./custom4.cpp
	$(CXX) -c -o $@ $(CUSTOM4_CXXFLAGS) $(CPPDEPS) $<

custom5_custom5.o: ./custom5.cpp
	$(CXX) -c -o $@ $(CUSTOM5_CXXFLAGS) $(CPPDEPS) $<



custom6_custom6.o: ./custom6.cpp
	$(CXX) -c -o $@ $(CUSTOM6_CXXFLAGS) $(CPPDEPS) $<

dbinfo_dbinfo.o: ./dbinfo.cpp
	$(CXX) -c -o $@ $(DBINFO_CXXFLAGS) $(CPPDEPS) $<


fieldinf1_fieldinf1.o: ./fieldinf1.cpp
	$(CXX) -c -o $@ $(FIELDINF1_CXXFLAGS) $(CPPDEPS) $<

xaction_xaction.o: ./xaction.cpp
	$(CXX) -c -o $@ $(XACTION_CXXFLAGS) $(CPPDEPS) $<

cgi_image_cgi_image.o: ./cgi_image.cpp
	$(CXX) -c -o $@ $(CGI_IMAGE_CXXFLAGS) $(CPPDEPS) $<

load_file_load_file.o: ./load_file.cpp
	$(CXX) -c -o $@ $(LOAD_FILE_CXXFLAGS) $(CPPDEPS) $<


updel_updel.o: ./updel.cpp
	$(CXX) -c -o $@ $(UPDEL_CXXFLAGS) $(CPPDEPS) $<

.PHONY: all clean






# Dependencies tracking:

-include ./*.d


Changes to config/libm.m4.

1
2
3
4
5
6
7
8
9

10
11
12
13
14
15
16
17
18
19

20
21
22
23
24
25
26
27
28




29
30
31
32

33
34
35
36
37




dnl @synopsis LIB_MATH
dnl 
dnl This macro figures out how whether programs using C's math routines
dnl need to link to libm or not.  This is common on SysV Unices.
dnl
dnl @category C
dnl @author Warren Young <warren@etr-usa.com>
dnl @version 1.2, 2006-03-06


AC_DEFUN([LIB_MATH],
[
	AC_MSG_CHECKING([whether -lm is needed to use C math functions])
	
	MYSQLPP_EXTRA_LIBS=
	TRY_LIBM=no
	AC_TRY_LINK(
		[ #include <math.h> ],
		[ floor(0); ], AC_MSG_RESULT(no), TRY_LIBM=yes)


	if test "x$TRY_LIBM" = "xyes"
	then
		save_LIBS=$LIBS
		LIBS="$LIBS -lm"
		AC_TRY_LINK(
			[ #include <math.h> ],
			[ floor(0); ],
			[ 
				MYSQLPP_EXTRA_LIBS=-lm 




				AC_MSG_RESULT(yes)
			],
			AC_MSG_ERROR([Failed to build program containing math functions!]))
		LIBS="$save_LIBS"

	fi

	AC_SUBST(MYSQLPP_EXTRA_LIBS)
])





|
|
|
<
<
<
<
<

>
|
|
<
|
<
<
<
<
<
|
>
|
<
<
<
<
<
<
|
<
>
>
>
>
|
<
|
<
>
|

<
<
|
>
>
>
>
1
2
3





4
5
6
7

8





9
10
11






12

13
14
15
16
17

18

19
20
21


22
23
24
25
26
<?xml version="1.0" ?>
<makefile>
	<include file="presets/simple.bkl"/>






	<set var="DBLDOLLAR">$(DOLLAR)$(DOLLAR)</set>
	<set var="ZLIB">yes</set>


	<set var="THREAD_TYPE">single</set>





	<if cond="FORMAT in ['msvc6prj', 'mingw']">
		<set var="THREAD_TYPE">multi</set>
	</if>






		

    <option name="BUILD">
        <values>debug,release</values>
        <values-description>Debug,Release</values-description>
        <default-value>debug</default-value>
        <description>

            Type of compiled binaries

        </description>
    </option>



    <set var="DEBUGINFO">
        <if cond="BUILD=='debug'">on</if>
        <if cond="BUILD=='release'">off</if>
    </set>
</makefile>

Changes to config/localtime_r.m4.

1

2
3
4
5
6
7
8

9


10


11

12





13
14




15
16
17
18

19
20
21




22
23
24
25
26
27
28
29
30
dnl @synopsis AX_C_LOCALTIME_R

dnl 
dnl This macro determines whether the C runtime library contains
dnl localtime_r(), a thread-safe replacement for localtime().
dnl
dnl @version 1.0, 2007/02/20
dnl @author Warren Young <mysqlpp@etr-usa.com>
AC_DEFUN([AX_C_LOCALTIME_R],

[


	AC_MSG_CHECKING([for localtime_r()])




	AC_TRY_RUN([





		#include <time.h>
		int main(void)




		{
			time_t tt;
			struct tm stm;
			localtime_r(&tt, &stm);

			return 0;
		}
	], [localtime_r_found=yes], [localtime_r_found=no], [localtime_r_found=no])





	AC_MSG_RESULT([$localtime_r_found])
	if test x"$localtime_r_found" = xyes
	then
		AC_DEFINE(HAVE_LOCALTIME_R, 1,
			[Define if you have the localtime_r() facility])
	fi
]) dnl AX_C_LOCALTIME_R

|
>
|
<
<
<
<
|
|
>
|
>
>
|
>
>

>
|
>
>
>
>
>
|
|
>
>
>
>
|
<
|
<
>
|
|
<
>
>
>
>

<
<
|
<
<
<
<

1
2
3




4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27

28

29
30
31

32
33
34
35
36


37




38
@echo off
if "%1" == "" goto error





set BASE_DIR=c:\mysql++
set INST_INC_DIR=%BASE_DIR%\include
set INST_LIB_DIR=%BASE_DIR%\%1

if not exist %BASE_DIR% mkdir %BASE_DIR%
if not exist %INST_INC_DIR% mkdir %INST_INC_DIR%
if not exist %INST_LIB_DIR% mkdir %INST_LIB_DIR%
if not exist %INST_LIB_DIR%\debug mkdir %INST_LIB_DIR%\debug
if not exist %INST_LIB_DIR%\release mkdir %INST_LIB_DIR%\release

copy lib\*.h "%INST_INC_DIR%" > NUL

if exist *.a goto install_mingw
copy debug\*.dll "%INST_LIB_DIR%\debug" > NUL
copy debug\*.lib "%INST_LIB_DIR%\debug" > NUL
copy release\*.dll "%INST_LIB_DIR%\release" > NUL
copy release\*.lib "%INST_LIB_DIR%\release" > NUL
goto install_done
:install_mingw
copy *.a "%INST_LIB_DIR%\debug" > NUL
echo WARNING: I assume you built a debug version of the library, as that
echo is what you get with MinGW unless you make a special effort.  You
echo must do a manual install if you make a release version.


:install_done

echo MySQL++ (%1 version) installed successfully!
goto end


:error
echo usage: install [subdir]
echo.
echo 	Installs MySQL++ into the given subdirectory of %BASE_DIR%



:end





Changes to config/mysql++.m4.

1
2
3

4

5



6


7
8
9
10
11
12
13
14
15
16
17
18
19
20

21







































22
23

24
25
26
27
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
56
57






58
59













60
61
62
63
64


65
66
67
68
69
70





71
72
73
74
75



76
77
78
79

80








81
82

83
84
85





86
87









88



89
90

91
92
93
94

95
96
97
98
99
100
101
102

103
104
105
106






107

108
109
110

111
112
113
114
115
116

117
118
119
120
121
122
123
124
125


126
127
128
129
130
131
#-######################################################################
# mysql++.m4 - Example autoconf macro showing how to find MySQL++
#	library and header files.

#

# Copyright (c) 2004-2009 by Educational Technology Resources, Inc.



#


# This file is free software; you can redistribute it and/or modify it
# under the terms of the GNU Lesser General Public License as published
# by the Free Software Foundation; either version 2.1 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
# Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public
# License along with MySQL++; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
# USA

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








































dnl @synopsis MYSQLPP_DEVEL

dnl 
dnl This macro tries to find the MySQL++ library and header files.
dnl
dnl We define the following configure script flags:
dnl
dnl		--with-mysqlpp: Give prefix for both library and headers, and try
dnl			to guess subdirectory names for each.  (e.g. tack /lib and
dnl			/include onto given dir name, and other common schemes.)
dnl		--with-mysqlpp-lib: Similar to --with-mysqlpp, but for library only.
dnl		--with-mysqlpp-include: Similar to --with-mysqlpp, but for headers

dnl			only.
dnl
dnl This macro depends on having the default compiler and linker flags
dnl set up for building programs against the MySQL C API.  The mysql.m4
dnl macro in this directory fits this bill; run it first.
dnl
dnl @version 1.3, 2009/11/22
dnl @author Warren Young <mysqlpp@etr-usa.com>






AC_DEFUN([MYSQLPP_DEVEL],


[
	dnl
	dnl Set up configure script macros
	dnl
	AC_ARG_WITH(mysqlpp,
		[  --with-mysqlpp=<path>     path containing MySQL++ header and library subdirs],
		[MYSQLPP_lib_check="$with_mysqlpp/lib64 $with_mysqlpp/lib $with_mysqlpp/lib64/mysql++ $with_mysqlpp/lib/mysql++"
		  MYSQLPP_inc_check="$with_mysqlpp/include $with_mysqlpp/include/mysql++"],
		[MYSQLPP_lib_check="/usr/local/mysql++/lib64 /usr/local/mysql++/lib /usr/local/lib64/mysql++ /usr/local/lib/mysql++ /opt/mysql++/lib64 /opt/mysql++/lib /usr/lib64/mysql++ /usr/lib/mysql++ /usr/local/lib64 /usr/local/lib /usr/lib64 /usr/lib"
		  MYSQLPP_inc_check="/usr/local/mysql++/include /usr/local/include/mysql++ /opt/mysql++/include /usr/local/include/mysql++ /usr/local/include /usr/include/mysql++ /usr/include"])
	AC_ARG_WITH(mysqlpp-lib,
		[  --with-mysqlpp-lib=<path> directory path of MySQL++ library],
		[MYSQLPP_lib_check="$with_mysqlpp_lib $with_mysqlpp_lib/lib64 $with_mysqlpp_lib/lib $with_mysqlpp_lib/lib64/mysql $with_mysqlpp_lib/lib/mysql"])
	AC_ARG_WITH(mysqlpp-include,






		[  --with-mysqlpp-include=<path> directory path of MySQL++ headers],
		[MYSQLPP_inc_check="$with_mysqlpp_include $with_mysqlpp_include/include $with_mysqlpp_include/include/mysql"])














	dnl
	dnl Look for MySQL++ library
	dnl
	AC_CACHE_CHECK([for MySQL++ library location], [ac_cv_mysqlpp_lib],


	[
		for dir in $MYSQLPP_lib_check
		do
			if test -d "$dir" && \
				( test -f "$dir/libmysqlpp.so" ||
				  test -f "$dir/libmysqlpp.a" )





			then
				ac_cv_mysqlpp_lib=$dir
				break
			fi
		done




		if test -z "$ac_cv_mysqlpp_lib"
		then
			AC_MSG_ERROR([Didn't find the MySQL++ library dir in '$MYSQLPP_lib_check'])

		fi









		case "$ac_cv_mysqlpp_lib" in

			/* ) ;;
			* )  AC_MSG_ERROR([The MySQL++ library directory ($ac_cv_mysqlpp_lib) must be an absolute path.]) ;;
		esac





	])
	AC_SUBST([MYSQLPP_LIB_DIR],[$ac_cv_mysqlpp_lib])













	dnl
	dnl Look for MySQL++ header file directory

	dnl
	AC_CACHE_CHECK([for MySQL++ include path], [ac_cv_mysqlpp_inc],
	[
		for dir in $MYSQLPP_inc_check

		do
			if test -d "$dir" && test -f "$dir/mysql++.h"
			then
				ac_cv_mysqlpp_inc=$dir
				break
			fi
		done


		if test -z "$ac_cv_mysqlpp_inc"
		then
			AC_MSG_ERROR([Didn't find the MySQL++ header dir in '$MYSQLPP_inc_check'])
		fi








		case "$ac_cv_mysqlpp_inc" in
			/* ) ;;
			* )  AC_MSG_ERROR([The MySQL++ header directory ($ac_cv_mysqlpp_inc) must be an absolute path.]) ;;

		esac
	])
	AC_SUBST([MYSQLPP_INC_DIR],[$ac_cv_mysqlpp_inc])

	dnl
	dnl Now check that the above checks resulted in -I and -L flags that

	dnl let us build actual programs against MySQL++.
	dnl
	case "$ac_cv_mysqlpp_lib" in
	  /usr/lib) ;;
	  *) LDFLAGS="$LDFLAGS -L${ac_cv_mysqlpp_lib}" ;;
	esac
	CPPFLAGS="$CPPFLAGS -I${ac_cv_mysqlpp_inc} -I${MYSQL_C_INC_DIR}"
	AC_MSG_CHECKING([that we can build MySQL++ programs])
	AC_COMPILE_IFELSE(


		[AC_LANG_PROGRAM([#include <mysql++.h>],
			[mysqlpp::Connection c(false)])],
		AC_MSG_RESULT([yes]),
		AC_MSG_ERROR([no]))
]) dnl End MYSQLPP_DEVEL

<
<
|
>
|
>
|
>
>
>
|
>
>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

|
>
|
<
<
<
<
<
<
<
<
<
>
|
|
<
<
<
<
<
<
>
>
>
>
>

<
>
>
|
<
|
<
<
<
<
<
|
|
|
|
|
|
>
>
>
>
>
>
|
<
>
>
>
>
>
>
>
>
>
>
>
>
>

<
<
<
<
>
>
|
<
|
<
<
<
>
>
>
>
>
|
<
<
<
<
>
>
>

<
|
<
>
|
>
>
>
>
>
>
>
>

<
>
|
<
|
>
>
>
>
>
|
<
>
>
>
>
>
>
>
>
>

>
>
>
|
<
>
|
<
|
<
>
|
<
<
<
<
|
|
|
>
|
<
<
<
>
>
>
>
>
>
|
>
|
<
<
>
|
<
<
|
<
<
>
|
|
|
|
|
|
|
|
|
>
>
|
|
|
<
|



1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
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
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70









71
72
73






74
75
76
77
78
79

80
81
82

83





84
85
86
87
88
89
90
91
92
93
94
95
96

97
98
99
100
101
102
103
104
105
106
107
108
109
110




111
112
113

114



115
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
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
191
192
193
194
195
196

197
198


/// \file cpool.h
/// \brief Declares the ConnectionPool class.

/***********************************************************************
 Copyright (c) 2007-2008 by Educational Technology Resources, Inc. and
 (c) 2007 by Jonathan Wakely.  Others may also hold copyrights on
 code in this file.  See the CREDITS file in the top directory of
 the distribution for details.

 This file is part of MySQL++.

 MySQL++ is free software; you can redistribute it and/or modify it
 under the terms of the GNU Lesser General Public License as published
 by the Free Software Foundation; either version 2.1 of the License, or
 (at your option) any later version.

 MySQL++ is distributed in the hope that it will be useful, but WITHOUT
 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
 License for more details.

 You should have received a copy of the GNU Lesser General Public
 License along with MySQL++; if not, write to the Free Software
 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
 USA
***********************************************************************/

#if !defined(MYSQLPP_CPOOL_H)
#define MYSQLPP_CPOOL_H

#include "beemutex.h"

#include <list>

#include <assert.h>
#include <time.h>

namespace mysqlpp {

#if !defined(DOXYGEN_IGNORE)
// Make Doxygen ignore this
class MYSQLPP_EXPORT Connection;
#endif

/// \brief Manages a pool of connections for programs that need more
/// than one Connection object at a time, but can't predict how many
/// they need in advance.
///
/// This class is useful in programs that need to make multiple
/// simultaneous queries on the database; this requires multiple
/// Connection objects due to a hard limitation of the underlying
/// C API.  Connection pools are most useful in multithreaded programs,
/// but it can be helpful to have one in a single-threaded program as
/// well.  Sometimes it's necessary to get more data from the server
/// while in the middle of processing data from an earlier query; this
/// requires multiple connections.  Whether you use a pool or manage
/// connections yourself is up to you, but realize that this class
/// takes care of a lot of subtle details for you that aren't obvious.
///
/// The pool's policy for connection reuse is to always return the 
/// \em most recently used connection that's not being used right now.
/// This ensures that excess connections don't hang around any longer
/// than they must.  If the pool were to return the \em least recently
/// used connection, it would be likely to result in a large pool of
/// sparsely used connections because we'd keep resetting the last-used 
/// time of whichever connection is least recently used at that moment.

class MYSQLPP_EXPORT ConnectionPool
{
public:









	/// \brief Create empty pool
	ConnectionPool() { }







	/// \brief Destroy object
	///
	/// If the pool raises an assertion on destruction, it means our
	/// subclass isn't calling clear() in its dtor as it should.
	virtual ~ConnectionPool() { assert(empty()); }


	/// \brief Returns true if pool is empty
	bool empty() const { return pool_.empty(); }


	/// \brief Grab a free connection from the pool.





	///
	/// This method creates a new connection if an unused one doesn't
	/// exist, and destroys any that have remained unused for too long.
	/// If there is more than one free connection, we return the most
	/// recently used one; this allows older connections to die off over
	/// time when the caller's need for connections decreases.
	///
	/// Do not delete the returned pointer.  This object manages the
	/// lifetime of connection objects it creates.
	///
	/// \retval a pointer to the connection
	Connection* grab();


	/// \brief Return a connection to the pool
	///
	/// Marks the connection as no longer in use.
	///
	/// The pool updates the last-used time of a connection only on
	/// release, on the assumption that it was used just prior.  There's
	/// nothing forcing you to do it this way: your code is free to
	/// delay releasing idle connections as long as it likes.  You
	/// want to avoid this because it will make the pool perform poorly;
	/// if it doesn't know approximately how long a connection has
	/// really been idle, it can't make good judgements about when to
	/// remove it from the pool.
	void release(const Connection* pc);





	/// \brief Remove all unused connections from the pool
	void shrink() { clear(false); }


protected:



	/// \brief Drains the pool, freeing all allocated memory.
	///
	/// A derived class must call this in its dtor to avoid leaking all
	/// Connection objects still in existence.  We can't do it up at
	/// this level because this class's dtor can't call our subclass's
	/// destroy() method.




	///
	/// \param all if true, remove all connections, even those in use
	void clear(bool all = true);


	/// \brief Create a new connection

	///
	/// Subclasses must override this.
	///
	/// Essentially, this method lets your code tell ConnectionPool
	/// what server to connect to, what login parameters to use, what
	/// connection options to enable, etc.  ConnectionPool can't know
	/// any of this without your help.
	///
	/// \retval A connected Connection object
	virtual Connection* create() = 0;


	/// \brief Destroy a connection
	///

	/// Subclasses must override this.
	///
	/// This is for destroying the objects returned by create().
	/// Because we can't know what the derived class did to create the
	/// connection we can't reliably know how to destroy it.
	virtual void destroy(Connection*) = 0;


	/// \brief Returns the maximum number of seconds a connection is
	/// able to remain idle before it is dropped.
	///
	/// Subclasses must override this as it encodes a policy issue,
	/// something that MySQL++ can't declare by fiat.
	///
	/// \retval number of seconds before an idle connection is destroyed
	/// due to lack of use
	virtual unsigned int max_idle_time() = 0;

private:
	//// Internal types
	struct ConnectionInfo {
		Connection* conn;

		time_t last_used;
		bool in_use;



		ConnectionInfo(Connection* c) :
		conn(c),




		last_used(time(0)),
		in_use(true)
		{
		}




		// Strict weak ordering for ConnectionInfo objects.
		// 
		// This ordering defines all in-use connections to be "less
		// than" those not in use.  Within each group, connections
		// less recently touched are less than those more recent.
		bool operator<(const ConnectionInfo& rhs) const
		{
			const ConnectionInfo& lhs = *this;
			return lhs.in_use == rhs.in_use ?


					lhs.last_used < rhs.last_used :
					lhs.in_use;


		}


	};
	typedef std::list<ConnectionInfo> PoolT;
	typedef PoolT::iterator PoolIt;

	//// Internal support functions
	Connection* find_mru();
	void remove_old_connections();

	//// Internal data
	PoolT pool_;
	BeecryptMutex mutex_;
};

} // end namespace mysqlpp


#endif // !defined(MYSQLPP_CPOOL_H)

Changes to config/mysql_ssl.m4.

1
2

3

4
5
6
7
8
9



10
11
12
13


14

15



16





17


dnl @synopsis MYSQL_WITH_SSL
dnl

dnl This macro determines whether mysql_ssl_set() API call exists.

dnl Requires at least MySQL 4.0.1. 
dnl 
dnl @version $Id$, $Date$
dnl @author Ovidiu Bivolaru <ovidiu@targujiu.rdsnet.ro>
AC_DEFUN([MYSQL_WITH_SSL],
[



    #
    # Check for mysql_ssl_set() in libmysqlclient(_r)
    #
    AC_CHECK_LIB($MYSQL_C_LIB_NAME, mysql_ssl_set, [


	AC_DEFINE(HAVE_MYSQL_SSL_SET,, Define if your MySQL library has SSL functions)

    ]) dnl AC_CHECK_LIB(mysqlclient, mysql_ssl_set)



]) dnl  MYSQL_WITH_SSL








|
<
>
|
>
|
<
|
<
<
|
>
>
>
|
<
|
|
>
>
|
>
|
>
>
>
|
>
>
>
>
>

>
>
1

2
3
4
5

6


7
8
9
10
11

12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
Prerequisite: Create Import Library

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	Before you can build MySQL++ with MinGW, you will need to
	create a MinGW-compatible import library for MySQL's C API
	library.  Assuming you installed MySQL in c:\mysql and MySQL++

	in c\mysql++, the commands to do this are:



		mkdir c:\mysql\lib\opt
		cd c:\mysql\lib\opt
	    dlltool -k -d c:\mysql++\libmysqlclient.def -l libmysqlclient.a



Building the Library and Example Programs
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	Now you can build MySQL++ with this command:
	
		mingw32-make -f Makefile.mingw

	Notice that we're using the MinGW-specific version of GNU
	make, not the Cygwin or MSYS versions.	This is in order to
	get proper path separator handling.

	If you didn't install MySQL in c:\mysql, it's probably simplest
	to just change the Makefile.mingw files.  Theoretically you
	could adjust the Bakefiles instead, but due to the way we're
	using Bakefile, it's a little difficult to rebuild Makefiles
	on Windows right now.

	If you want to change the install location, that is in
	install.bat.

Changes to config/socket_nsl.m4.

1
2

3
4
5
6
7
8
9
10
11
12
13
14
15
16

17
18
19
20
21
22





23
24
25
26
27
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
56
57

58
59
60
61
62
63
64
65
66
67
68


69




70
71

72

dnl @synopsis LIB_SOCKET_NSL
dnl 

dnl This macro figures out what libraries are required on this platform
dnl to link sockets programs.
dnl
dnl The common cases are not to need any extra libraries, or to need
dnl -lsocket and -lnsl.  We need to avoid linking with libnsl unless
dnl we need it, though, since on some OSes where it isn't necessary it
dnl will totally break networking.  Unisys also includes gethostbyname()
dnl in libsocket but needs libnsl for socket().
dnl
dnl @category Misc
dnl @author Warren Young <mysqlpp@etr-usa.com>
dnl @version 1.5, 2006-03-06

AC_DEFUN([LIB_SOCKET_NSL],

[
	save_LIBS="$LIBS"

	AC_MSG_CHECKING([whether -lsocket is needed])
	TRY_LSOCKET=no
	AC_TRY_LINK(





		[ 
			#include <sys/types.h>
			#include <sys/socket.h> 
			#include <netinet/in.h>
			#include <arpa/inet.h>
		],
		[ socket(AF_INET, SOCK_STREAM, 0); ],
		AC_MSG_RESULT(no), TRY_LSOCKET=yes)



	if test "x$TRY_LSOCKET" = "xyes"
	then


		LIBS="-lsocket $LIBS"
		AC_TRY_LINK(
			[ 


				#include <sys/types.h>
				#include <sys/socket.h> 
				#include <netinet/in.h>
				#include <arpa/inet.h>
			],
			[ socket(AF_INET, SOCK_STREAM, 0); ],
			[ 
				MYSQLPP_EXTRA_LIBS="-lsocket $MYSQLPP_EXTRA_LIBS"
				AC_MSG_RESULT(yes)
			],
			AC_MSG_ERROR([failed to link using -lsocket!]))



	fi

	AC_MSG_CHECKING([whether -lnsl is needed])
	TRY_LNSL=no
	AC_TRY_LINK(
		[ #include <netdb.h> ],
		[ gethostbyname("gna.org"); ],
		AC_MSG_RESULT(no), TRY_LNSL=yes)

	if test "x$TRY_LNSL" = "xyes"

	then
		LIBS="-lnsl $LIBS"
		AC_TRY_LINK(
			[ #include <netdb.h> ],
			[ gethostbyname("gna.org"); ],
			[ 
				MYSQLPP_EXTRA_LIBS="-lnsl $MYSQLPP_EXTRA_LIBS"
				AC_MSG_RESULT(yes)
			],
			AC_MSG_ERROR([failed to link using -lnsl!]))
	fi







	AC_SUBST(MYSQLPP_EXTRA_LIBS)
])



<
|
>
|
|
|
|
|
<
<
<
<
<
<
<
|
<
>
|
<
|
|
<
<
>
>
>
>
>
|
<
<
<
<
<
<
<
>
>

|
|
>
>
|
<
<
>
>
<
<
<
<
<
<
|
<
<
<
<
>
>
>

|
<
<
<
<
<
<

<
>

<
<
|
<
<
<
<
<
<

>
>

>
>
>
>
|
<
>

>

1
2
3
4
5
6
7







8

9
10

11
12


13
14
15
16
17
18







19
20
21
22
23
24
25
26


27
28






29




30
31
32
33
34






35

36
37


38






39
40
41
42
43
44
45
46
47

48
49
50

#!/bin/sh
CFG_FILE=~/.mysqlpp
if [ ! -f $CFG_FILE ]
then
	echo Create $CFG_FILE, please.
	echo
	exit 1







fi

. $CFG_FILE


if [ ! -f config.h ]
then


	echo Package hasn't yet been built, or you aren't in the top
	echo mysql++ directory.
	echo
	exit 1
fi








VERSION=`cat mysql++.spec | grep ^Version: | cut -f2 -d' '`
TMPDIR=`mktemp -d /tmp/mysqlpp-up.XXXXXXXXXX`

if [ "$1" = "src" ]
then
	if [ ! -e mysql++-$VERSION.tar.gz ]
	then
		make dist


	fi
	cp mysql++-$VERSION.tar.gz $TMPDIR











	if [ ! -e /usr/src/redhat/RPMS/i386/mysql++-manuals-$VERSION-1.i386.rpm ]
	then
		make rpm
	fi
	cp /usr/src/redhat/RPMS/i386/mysql++-manuals-$VERSION-1.i386.rpm $TMPDIR








	if [ ! -e /usr/src/redhat/SRPMS/mysql++-$VERSION-1.src.rpm ]
	then


		make srpm






	fi
	cp /usr/src/redhat/SRPMS/mysql++-$VERSION-1.src.rpm $TMPDIR
fi

cp /usr/src/redhat/RPMS/i386/mysql++-$VERSION-1.i386.rpm \
		$TMPDIR/mysql++-$VERSION-1.`./osver`.i386.rpm
cp /usr/src/redhat/RPMS/i386/mysql++-devel-$VERSION-1.i386.rpm \
		$TMPDIR/mysql++-devel-$VERSION-1.`./osver`.i386.rpm


scp $SSH_OPTIONS $TMPDIR/* $SSH_TARGET

rm -rf $TMPDIR

Changes to config/stl_slist.m4.

1
2
3
4
5
6
7
8
9
10
11

12
13
14
15
16

17

18

19
20


21

22

23
24
25

26

27


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
dnl @synopsis STL_SLIST_EXTENSION
dnl 
dnl This macro determines whether the local STL implementation includes
dnl a singly-linked list template, slist, and if so, where it is.
dnl
dnl @version 1.2, 2005/07/22
dnl @author Warren Young <mysqlpp@etr-usa.com>
AC_DEFUN([STL_SLIST_EXTENSION],
[
	AC_MSG_CHECKING([for STL slist extension])


	AC_COMPILE_IFELSE(
		[AC_LANG_PROGRAM(
			[#include <slist>],
			[slist<int> l])],
		AC_DEFINE(HAVE_GLOBAL_SLIST, 1,

			[ Define if you have ::slist container in <slist> ]),

		TRY_NEXT=yes)


	if test -z "$TRY_NEXT"


	then

		SLIST_LOC="<slist>, global scope"

	else
		TRY_NEXT=""
		AC_COMPILE_IFELSE(

			[AC_LANG_PROGRAM(

				[#include <slist>],


				[std::slist<int> l])],
			AC_DEFINE(HAVE_STD_SLIST, 1,
				[ Define if you have std::slist container in <slist> ]),
			TRY_NEXT=yes)



		if test -z "$TRY_NEXT"




		then
			SLIST_LOC="<slist>, namespace std"


		else
			TRY_NEXT=""
			AC_COMPILE_IFELSE(
				[AC_LANG_PROGRAM(
					[#include <ext/slist>],

					[__gnu_cxx::slist<int> l])],


				AC_DEFINE(HAVE_EXT_SLIST, 1,



					[ Define if you have __gnu_cxx:slist container in <ext/slist> ]),
				SLIST_LOC="not found")


			if test -z "$SLIST_LOC"






			then
				SLIST_LOC="<ext/slist>, namespace __gnu_cxx"
			fi
		fi
	fi

	AC_MSG_RESULT([$SLIST_LOC])
]) dnl STL_SLIST_EXTENSION


|
|
|
|
|
|
|
|
|
|

>
|
<
|
|
|
>
|
>
|
>

|
>
>
|
>
|
>
|
|
|
>
|
>
|
>
>
|
|
<
<
>

>
|
>
>
>
>
|
|
>
>
|
|
|
|
|
>
|
>
>
|
>
>
>
|
<
>

<
>
>
>
>
>
>
|
|
|
|
<

<
<
>

1
2
3
4
5
6
7
8
9
10
11
12
13

14
15
16
17
18
19
20
21
22
23
24
25
26
27
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
56
57
58
59
60
61
62
63
64
65
66

67
68

69
70
71
72
73
74
75
76
77
78

79


80
81
The user manual is written in XML DocBook format, version 4.2. We
restrict ourselves to Simplified DocBook 1.1 as much as possible.
(Why these versions? They're the newest supported on the oldest system
I still use, Red Hat Linux 9.)

If you're looking to hack on the manual, here are some helpful resources
for getting up to speed on DocBook:


Mills' "Installing And Using An XML/SGML DocBook Editing Suite" article:

	http://supportweb.cs.bham.ac.uk/documentation/tutorials/docsystem/build/tutorials/docbooksys/docbooksys.html


	This is the best tutorial I've found.
	

Walsh and Muellner's _Simplified DocBook: The Definitive Guide_ book:

	http://www.docbook.org/tdg/simple/en/html/sdocbook.html

	This is the most accessible reference.


Walsh and Muellner's _DocBook: The Definitive Guide_ book, second
edition, online version:

	http://www.docbook.org/tdg/en/html/docbook.html

	This is the official DocBook referece; the "Simplified" guide is a
	subset of this book.


DocBook FAQ:

	http://www.dpawson.co.uk/docbook/

	Go here when you have a question that the tutorials and references
	do not answer.




xsltproc:

	http://xmlsoft.org/XSLT/

	This is the XSL processor that takes the DocBook file and an XSL
	stylesheet and produces either HTML or XSL+FO. (The latter is an
	intermediate step towards any of several print-oriented formats,
	such as PDF or TeX.) If your system has GNOME on it, you probably
	have this installed already.

	You will also need the standard set of DocBook style sheets.  On
	Red Hat Linux and Fedora Core, these are in the docbook-style-xsl
	package.


FOP:

	http://xml.apache.org/fop/

	This is the XSL+FO document processor we use to build the PDF
	files. ('make pdf')

	If for some reason you have trouble getting FOP working, there's
	an alternate method available as 'make oldpdf' which uses xsltproc
	and pdfxmltex. It produces a pretty ugly PDF, but you probaly
	already have the tools installed, if you have any of them at all.

	pdfxmltex is in the xmltex package on Fedora Core 3.


	If neither of those work for you, you could use the OpenJade
	tool chain instead. (http://openjade.org/) This is SGML DocBook
	rather than the more modern XML DocBook I favor, but the only
	XML-specific thing we are using is local XSL stylesheets. You
	could ignore them and use the standard DSSSL stylesheets
	instead. I avoid the SGML tool chain only because I've had
	trouble with it in the past.


The official DocBook site:




	http://docbook.org/

Changes to doc/README-devel-RPM.txt.


1






















































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































2




3





























































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































4

5









6

7











8
























































9













































































10

mysql++-devel RPM installs the files you need when building your own






















































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































MySQL++ based programs, as well as documentation and examples that




can help you learn how to use the library.































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































The MySQL++ header files are in /usr/include/mysql++, the library









is in /usr/lib, and the example programs' source code is in

/usr/share/doc/mysql++-devel-*/examples.  For more information on











the examples, see the README-examples.txt file in the directory
























































containing the examples.














































































>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

>
|
>
>
>
>
>
>
>
>
>
|
>
|
>
>
>
>
>
>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
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
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
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
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
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
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
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
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
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
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
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
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
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
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
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
1694
1695
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
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
1883
1884
1885
1886
1887
1888
1889
1890
1891
1892
1893
1894
1895
1896
1897
1898
1899
1900
1901
1902
1903
1904
1905
1906
1907
1908
1909
1910
1911
1912
1913
1914
1915
1916
1917
1918
1919
1920
1921
1922
1923
1924
1925
1926
1927
1928
1929
1930
1931
1932
1933
1934
1935
1936
1937
1938
1939
1940
1941
1942
1943
1944
1945
1946
1947
1948
1949
1950
1951
1952
1953
1954
1955
1956
1957
1958
1959
1960
1961
1962
1963
1964
1965
1966
1967
1968
1969
1970
1971
1972
1973
1974
1975
1976
1977
1978
1979
1980
1981
1982
1983
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993
1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
2027
2028
2029
2030
2031
2032
2033
2034
2035
2036
2037
2038
2039
2040
2041
2042
2043
2044
2045
2046
2047
2048
2049
2050
2051
2052
2053
2054
2055
2056
2057
2058
2059
2060
2061
2062
2063
2064
2065
2066
2067
2068
2069
2070
2071
2072
2073
2074
2075
2076
2077
2078
2079
2080
2081
2082
2083
2084
2085
2086
2087
2088
2089
2090
2091
2092
2093
2094
2095
2096
2097
2098
2099
2100
2101
2102
2103
2104
2105
2106
2107
2108
2109
2110
2111
2112
2113
2114
2115
2116
2117
2118
2119
2120
2121
2122
2123
2124
2125
2126
2127
2128
2129
2130
2131
2132
2133
2134
2135
2136
2137
2138
2139
2140
2141
2142
2143
2144
2145
2146
2147
2148
2149
2150
2151
2152
2153
2154
2155
2156
2157
2158
2159
2160
2161
2162
2163
2164
2165
2166
2167
2168
2169
2170
2171
2172
2173
2174
2175
2176
2177
2178
2179
2180
2181
2182
2183
2184
2185
2186
2187
2188
2189
2190
2191
2192
2193
2194
2195
2196
2197
2198
2199
2200
2201
2202
2203
2204
2205
2206
2207
2208
2209
2210
2211
2212
2213
2214
2215
2216
2217
2218
2219
2220
2221
2222
2223
2224
2225
2226
2227
2228
2229
2230
2231
2232
2233
2234
2235
2236
2237
2238
2239
2240
2241
2242
2243
2244
2245
2246
2247
2248
2249
2250
2251
2252
2253
2254
2255
2256
2257
2258
2259
2260
2261
2262
2263
2264
2265
2266
2267
2268
2269
2270
2271
2272
2273
2274
2275
2276
2277
2278
2279
2280
2281
2282
2283
2284
2285
2286
2287
2288
2289
2290
2291
2292
2293
2294
2295
2296
2297
2298
2299
2300
2301
2302
2303
2304
2305
2306
2307
2308
2309
2310
2311
2312
2313
2314
2315
2316
2317
2318
2319
2320
2321
2322
2323
2324
2325
2326
2327
2328
2329
2330
2331
2332
2333
2334
2335
2336
2337
2338
2339
2340
2341
2342
2343
2344
2345
2346
2347
2348
2349
2350
2351
2352
2353
2354
2355
2356
2357
2358
2359
2360
2361
2362
2363
2364
2365
2366
2367
2368
2369
2370
2371
2372
2373
2374
2375
2376
2377
2378
2379
2380
2381
2382
2383
2384
2385
2386
2387
2388
2389
2390
2391
2392
2393
2394
2395
2396
2397
2398
2399
2400
2401
2402
2403
2404
2405
2406
2407
2408
2409
2410
2411
2412
2413
2414
2415
2416
2417
2418
2419
2420
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
2475
2476
2477
2478
2479
2480
2481
2482
2483
2484
2485
2486
2487
2488
2489
2490
2491
2492
2493
2494
2495
2496
2497
2498
2499
2500
2501
2502
2503
2504
2505
2506
2507
2508
2509
2510
2511
2512
2513
2514
2515
2516
2517
2518
2519
2520
2521
2522
2523
2524
2525
2526
2527
2528
2529
2530
2531
2532
2533
2534
2535
2536
2537
2538
2539
2540
2541
2542
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
2587
2588
2589
2590
2591
2592
2593
2594
2595
2596
2597
2598
2599
2600
2601
2602
2603
2604
2605
2606
2607
2608
2609
2610
2611
2612
2613
2614
2615
2616
2617
2618
2619
2620
2621
3.0.1, 2008.03.19 (r2255)

    o String objects can now be compared to mysqlpp::null directly.

    o Added a template operator== and operator!= to String, syntactic
      sugar for the existing String::compare() methods.

    o String::compare() now returns 0 ("equal") when one of the
      strings is an uninitialized String() (no refcounted buffer)
      and the other is empty.  It used to consider any initialized
      string greater than an uninitted one.  An uninitialized String
      appears empty, though, so this was incorrect.

    o Made Connection::thread_aware(), thread_start() and thread_end()
      static methods, so they can be called before you create your
      first connection.  Ditto for DBDriver versions of these methods.

    o Calling Connection::thread_start() and thread_end() in
      examples/cpool.cpp, as appropriate.  Above changes were necessary
      to make this work sensibly.

    o Made ConnectionPool::release() virtual, so your pool subclass can
      override it.

    o Added ConnectionPool::size(), so a subclass can know the current
      number of extant connections.

    o No longer single-quoting NOW() call generated for default
      init of DateTime type when building queries from SSQLS objects
      in Query::insert(), replace() and update().  The template query
      and stream interfaces of Query treated NOW() correctly already.

    o Fixed a bug that left SSQLS::table_override_ uninitted if
      you used certain of the generated ctors or set() member
      functions instead of others used by the examples.  This could
      cause a crash any time you caused SSQLS.table() to be called,
      such as when passing the SSQLS to Query::insert().

    o Minor memset bug fixed in test/uds.cpp.  Patch by Dave Jones.


3.0.0, 2008.02.29 (r2236) The "Giant Leap Forward" release

    THIS IS NOT A DROP-IN REPLACEMENT FOR MySQL++ v2.x!

    You will have to recompile your program against this version
    of the library, and you will almost certainly have to make code
    changes as well.  Please see these sections in the user manual
    for information on migrating your code to this new version:

    http://tangentsoft.net/mysql++/doc/html/userman/breakages.html#api-3.0.0
    http://tangentsoft.net/mysql++/doc/html/userman/breakages.html#abi-3.0.0

    o Added ConnectionPool class, primarily to let multithreaded
      programs share a set of Connection objects safely in situations
      where it isn't acceptable to have a Connection per thread.

    o Created examples/cpool.cpp to demonstrate this new class.

    o Added RefCountedPointer template, which provides automatic
      memory management and data sharing.  It's not intended
      for use outside of MySQL++ itself, but it's the mechanism
      behind everything below where reference counting is mentioned.
      I created the initial version of it, but Jonathan Wakely almost
      completely rebuilt it, and Joseph Artsimovich provided helpful
      commentary and advice as well.

    o Many improvements to Specialized SQL Structures (SSQLS):

      - Renamed custom* to ssqls*.  There's still a custom.h which
        #includes ssqls.h for you, but it's only intended to ease
        the transition to the new name.  It will go away in a future
        release, probably as soon as v3.1.

      - SSQLSes are finally compatible with Null<>-wrapped types.  This
        feature is based loosely on the "Waba" patch posted to the
        mailing list back in the v2.0 days, but extended to allow
        Null<T> types for key fields.  (The Waba patch only allowed
        these types in non-key fields.)

      - It's no longer necessary to define a different SSQLS for each
        different field set you use in queries.  That is to say,
        you can define an SSQLS for an entire table and store just a
        subset of the table in it now, with the other fields keeping
        default values.  Removed examples/custom6.cpp, as custom1.cpp
        can now demonstrate the same thing, implicitly.

      - An SSQLS's field order no longer has to match the order of
        fields in the result set it is populated from.

      - As a result of previous, removed sql_create_c_order_* macros;
        they have no purpose now.

      - Removed order parameters from sql_create_complete_*, which now
        gives it the same functionality as sql_create_c_names_* so
        removed the latter, too.

      - Removed "basic" variants of SSQLS creation macros.  They've
        been unofficially deprecated by dint of being all but
        undocumented and unexemplified for a very long time now.

      - It's now possible to use mysqlpp::String, Date, DateTime, and
        Time types in the key field positions in an SSQLS as they
        now support the necessary comparison interfaces.

      - If you use a floating-point data type in one of the key field
        positions, it no longer uses exact comparison logic.  Instead,
        it now does [in]equality comparisons by testing whether the
        difference between two floating-point values is less than a
        configurable threshold defaulting to 0.00001.
    
      - You can now use 'bool' type in an SSQLS.

      - Renamed _table static member variable in each SSQLS to table_
        and made it private.  There are now public setter and getter
        methods, table().

      - Added per-instance table name overriding via instance_table()
        setter.  table() getter returns static version if this is not
        set, so it's still a global setting by default.

    o You can now use mysqlpp::null as a template query parameter to
      get a SQL null.

    o Replaced template ColData_Tmpl<T>:

      - Used to have typedef ColData_Tmpl<std::string> MutableColData.
        It was used only once within MySQL++ itself, and was never
        documented as a class for end users.  This one use within
        the library was a crock, so we just replaced this use with
        std::string and removed the typedef.

      - This left just one use of ColData_Tmpl<T>, instantiating it
        with the MySQL++ utility class const_string, basically a
        clone of std::string with all the mutating features removed.
        Folded the functionality of const_string into the template,
        renamed the result to String, and deleted the const_string
        class.  It'd be a complete std::string replacement -- with
        SQL-related enhancements -- if it were modifiable, but MySQL++
        doesn't need it to be modifiable.  Yet, it's still the closest
        thing MySQL++ has to its own string type; thus the name.

      - Replaced its internal buffer management with a much more
        clever reference counted scheme.  This shows its greatest
        advantage in the return from Row::operator[](), which for
        technical reasons must return by value, not by reference
        as is more common.  This lets you pass around Strings by
        value while having the efficiency of reference semantics.
        This can be important with large return values, like BLOBs.

      - Converting String to numeric types (ints, floats...) uses a
        new, cleaner system by Jonathan Wakely.  Unless you were
        abusing weaknesses in the old system, you won't see a
        difference.  It's just more robust and flexible.

    o Redesigned SQLString:

      - It used to derive from std::string, and while MySQL++'s
        internals did use it in place of std::string, these places
        didn't take advantage of the additional features offered
        by SQLString.  So, replaced all those uses with std::string.

      - All the remaining uses are MySQL++ public interfaces that
        need to be able to accept any of many different data types,
        and we want that data to be automatically converted to a
        SQL-compatible string form.  Because it no longer has the
        parentage to be a general-purpose string type and MySQL++ has
        a new contender for that role (String), renamed SQLString to
        SQLTypeAdapter to reflect its new, limited purpose.  ("STA"
        for short.)

      - Since we don't have the std::string base class to manage the
        string buffer any more, using the same reference counted
        buffer mechanism as String.  In addition to saving code by
        not creating yet another buffer management mechanism, it means
        objects of the two classes can share a buffer when you assign
        one to the other or pass one to the other's copy ctor.

      - Added many more conversion ctors.

      - STA interfaces using the 'char' data type now treat them as
        single-character strings instead of one-byte integers, as
        does the Standard C++ Library.

      - Added mysqlpp::tiny_int interfaces to STA to replace the
        former char interfaces for those needing one-byte integers.

    o As a result of the ColData -> String redesign, removed
      Row::raw_*().  Before String copies were efficient, this
      was helpful in accessing BLOB data efficiently.  It was also
      required back when ColData didn't deal correctly with embedded
      null characters, but that reason is gone now, too.

    o Row::operator[](const char*) no longer unconditionally throws the
      BadFieldName exception when you ask for a field that doesn't
      exist.  It will still throw it if exceptions are enabled, but if
      not, it'll just return an empty String.  This was necessary to
      make the SSQLS subset and field order independence features work.

    o Similarly, Result::field_num() returns -1 when exceptions are
      disabled and you ask for a field that doesn't exist.

    o You can now use the OptionalExceptions mechanism to disable
      exceptions on const MySQL++ objects.

    o Redesigned query result classes:

      - Instead of Result deriving from ResUse, the two derive from
        a common base class -- ResultBase -- containing the bits that
        are truly the same between them.  Before, Result inherited
        several methods that didn't really make sense for "store"
        query result sets.

      - Renamed Result to StoreQueryResult and ResUse to UseQueryResult
        so it's clearer what each is for.

      - Renamed ResNSel to SimpleResult.

      - Made all SimpleResult data members private and hid them behind
        const accessor functions of the same name.

      - The result set classes all used to be friends of Connection
        for various lame reasons.  Since they are created by Query,
        and Query has a good reason for a strong relationship with
        Connection, moved Connection access out of each result set
        class into the code in Query that creates that type of result
        set object.

      - StoreQueryResult now derives from vector<Row> in addition to
        ResultBase; it used to merely emulate a vector of Rows, poorly.
        It can now dispose of the MYSQL_RESULT at the end of object
        construction, because it creates all the Row objects up front
        instead of on the fly.  And as a result of *that*, operator[]
        returns by reference instead of by value, operator -> works
        correctly on iterators, all STL algorithms work, etc., etc.

      - IMPORTANT COMPATIBILITY BREAK: because we used fetch_row()
        stuff in Result previously, it was okay to index past the
        end of the result set: you'd just get a falsy Row when you
        did this, just as happens when doing the same thing in a
        "use" query.  The simple1 and simple2 examples did this,
        so it's likely that code exists that takes advantage of this
        misfeature.  New versions of these examples show how to index
        through a StoreQueryResult without running past its end.

      - ResUse used to delay creation of its FieldNames and FieldTypes
        objects until the point of need.  This had several implications
        for thread and exception safety that we fix by just creating
        them in the ctor.  If your code is multi-threaded and was
        avoiding certain usage patterns due to crashes, it's worth
        trying your preferred way again.

      - Result sets create a few data structures to hold information
        common to all rows in that set.  The row objects need access
        to these shared data structures, so on creation each gets
        a pointer back to the result set object that creates it.
        This was efficient, but required that a result set object
        outlive any row objects it creates.  Now these shared data
        structures are reference-counted, decoupling the lifetime of
        the child row objects from their result set parent.

      - Copy operations for result sets used to actually be "moves"
        before, for efficiency.  (MySQL++ itelf only copied result
        sets in returning them by value from the query execution
        methods of Query, so this was acceptable if you didn't do
        anything uncommon with these objects.)  Reference counted
        data structures allow us to have copy semantics now without
        sacrificing efficiency.

      - You can now use Query::storein() with an STL container of Row
        objects now, instead of having to use SSQLSes.  The lifetime
        issue guaranteed a crash if you tried this before.

      - Removed a bunch of unnecessary alias methods:

        - columns() -> num_fields()
        - names()   -> field_names()
        - rows()    -> num_rows()
        - types()   -> field_types()

      - Renamed several methods for grammar reasons:

        - fields(unsigned int)      -> field(unsigned int)
        - names(const std::string&) -> field_num(const std::string&)
        - names(int)                -> field_name(int)
        - types(int)                -> field_type(int)

      - Removed several "smelly" methods:

        - purge()
        - raw_result()
        - reset_names()
        - reset_field_names()
        - reset_types()
        - reset_field_types()

    o Field class used to just be a typedef for the corresponding C
      API class.  Now it's a real C++ class providing a more MySQL++
      sort of interface, plus good OO things like information hiding
      and implementation detail abstraction.  This changes several
      things about the interface.

    o Fields class was basically a specialized std::vector work-alike
      for dealing with the C API to get access to MYSQL_FIELD objects
      and present them as contained Field objects.  New Field type
      let us replace it with "typedef std::vector<Field> Fields"

    o Major improvements to the quoting and escaping mechanisms:

      - Replaced almost all of the type-specific interfaces in manip.h
        with a single version taking STA.  The compiler can convert
        almost anything to STA without losing any information we need
        for correct quoting and escaping.  This has the side benefit
        that we can now do correct quoting and escaping for more data
        types now, including plain C and C++ string types.

      - Fixed a bug in quote_double_only manipulator for String: was
        using single quotes by mistake.

      - Escaping and quoting only works in instances where MySQL++
        can tell you're building a SQL query and are using a data type
        that requires it.  This affects many things, but the one most
        likely to cause trouble is that inserting MySQL++'s quoting
        and escaping manipulators in non-Query ostreams is now a no-op.

      - Added escape_string() member functions to Query and
        SQLQueryParms::escape_string(), and removed the global function
        of the same name.  Because these are tied indirectly to a
        Connection object, this also has the effect that escaping is
        now aware of the current default character set used by the
        database server.  There's only one case where this isn't done
        now, and that's when we're disconnected from the server.

      - Previous two items form a trade-off: if your code was depending
        on MySQL++ to get SQL escaping and it no longer happens for
        what we consider a good reason, you can build a replacement
        mechanism using these new functions.  Quoting needs no special
        support in MySQL++.

      - Removed 'r' and 'R' template query parameter modifiers,
        which meant "always quote" and "always quote and escape"
        regardless of the data type of the parameter.  There are no
        corresponding manipulators (for good reason), so the removal
        restores symmetry.

    o Created DBDriver class from code previously in Connection and
      Query to almost completely wrap the low-level MySQL C API:

      - Connection creates a DBDriver object upon connection and
        passes a pointer to it down to Query objects it creates.
        In turn, they pass the pointer on to any of their children
        that need access to the C API.

      - Nothing outside DBDriver calls the C API directly now, though
        DBDriver leaks C API data structures quite a lot, so this
        feature doesn't constitute "database independence."  See the
        Wishlist for what must be done to get to that point.

    o Completely redesigned the connection option setting mechanism:

      - There's now just a single Connection::set_option() method that
        takes a pointer to the abstract Option base class, and there is
        an Option subclass for every connection option we understand.
        Thus, type errors are now caught at compile time instead of
        at run time.

      - Replaced Connection::enable_ssl() with SslOption class.

      - Enabling data compression and setting the connection timeout
        are no longer set via parameters to Connection interfaces.
        These are now set with CompressOption and ConnectTimeoutOption.

      - Similarly, removed client_flag parameters from Connection's
        ctor and connect() method and added corresponding Option
        subclasses.  There's about a dozen, so rather than list them
        here, look for similarly-named classes in lib/options.h.

    o Added Connection::count_rows() to execute "SELECT COUNT(*) FROM
      tablename" queries for you.

    o Moved Connection::affected_rows(), info() and insert_id() methods
      to class Query, as they relate to the most recently-executed
      query, not to the connection.

    o Several method name changes in Connection:

      - client_info()   -> client_version()
      - host_info()     -> ipc_info()
      - proto_info()    -> protocol_version()
      - server_info()   -> server_version()
      - stat()          -> status()

    o Removed Connection::api_version().  It does the same thing as
      client_version().

    o Lots of changes to Date, DateTime, and Time classes:

      - If you use the default constructor for DateTime and don't
        subsequently set its year, month, day, hour, minute or second
        data members to nonzero values, it becomes the SQL function
        "NOW()" in a query string.  You can also use DateTime::now()
        as syntactic sugar for this.

      - As a result of above, had to hide all of DateTime's data
        members behind accessor functions, to keep the state of the
        object consistent.  (If it's initialized as "now" and you
        give it an explicit year value, say, it is no longer "now",
        so the setter has to clear the now-flag.)  There are getters
        and setters for year, month, day, hour, minute and second,
        all named after the member.

      - Did the same for Date and Time for consistency, even though it
        isn't technically required.

      - The sql_timestamp typedef now aliases DateTime instead of Time.

      - Renamed template class DTbase<T> to Comparable<T>.  The fact
        that it's the common base class of all date and time classes
        is irrelevant; making subclasses comparable is what it does,
        so that's what it should be named after.

      - Added a DateTime ctor taking discrete year, month, day, hour,
        minute, and second values.

      - Implicit conversion from stringish types to the date and time
        types is no longer allowed.  This is part of the "Waba"
        Null<T> patch mentioned above; allowing implicit conversions
        would break this new feature.

      - Added operator std::string and str() methods to all of these
        classes.  Adding this to the existing operator << support, you
        now have several ways to convert these objects to string form.

      - Added time_t conversion to Date and Time classes.  DateTime
        already had it, since it's more legitimate to convert time_t
        to DateTime, but you could already "slice" it with something
        like Time(DateTime(time(0))) so there's no point pretending
        you can't get from time_t to Date or Time.  Might as well
        legitimize it.

    o Improved tiny_int class:
        
      - Turned it into a template parameterized on the value type so
        you can get both signed and unsigned TINYINTs

      - Changed the sql_tinyint and sql_tinyint_unsigned typedefs to
        use mysqlpp::tiny_int<VT> instead of raw chars

      - Added a bool conversion ctor and operator, and typedef'd it
        to sql_bool and sql_boolean to match MySQL server behavior

    o Added many more sql_* typedefs.  We now have a typedef for every
      type the MySQL server knows about, including those it supports
      just for compatibility with other database servers.

    o Changed the sql_*int* typedefs to use integer types of the same
      size as the MySQL server.  (Run test/inttypes.cpp to test it.)

    o Added copy ctor and assignment operator to Row.

    o Row::operator[]() takes int now instead of unsigned int.
      This finally (!) makes it possible to say row[0] without the
      compiler giving an ambiguous overload error.

    o Changed all uses of row.at(0) in the examples to row[0]

    o Added operator[] to all classes that only had at().

    o Query now automatically resets itself unless the query fails
      or you're using template queries.  In either case, the contents
      of the query's internal buffers are considered precious,
      either for debugging, or future queries.  Except when using
      template queries, this means you may be able to avoid calling
      Query::reset() entirely.  It's still safe to call reset()
      as before, just unnecessary most of the time.

    o Removed reset_query parameter from all Query methods.  It was
      almost completely broken before, and above change does what
      was really wanted to begin with.

    o Query::store_next() and Result::fetch_row() no longer throw
      the EndOfResults and EndOfResultSets exceptions; these are not
      exceptional conditions!  These methods simply return false now.

    o Removed examples/usequery.cpp: there's no essential difference
      between what it did and what examples/simple3.cpp does now as
      a result of the previous change.

    o Added Query::exec(void), paralleling Query::execute(void).

    o Removed Query::preview().  The most direct replacement is str(),
      which has always done the same thing.

    o You can now insert a Query object into an ostream to get a copy
      of the built query.  This means Query::str() is only necessary
      when using template queries.

    o Removed overloads of Query::execute(), store(), and use()
      that take const char*.  It was redundant because const char*
      converts implicitly to STA, for which overloads already exist.

    o Renamed Query::def to Query::template_defaults to make its
      purpose clearer.

    o Query::error() now returns const char*, not a std::string by
      value.  There's no point in making a copy of the error string.
      The method is now const as well, as it doesn't change the
      Query object.

    o Added Query::errnum(), which just wraps Connection::errnum().

    o Added error number parameters and accessor functions to BadQuery,
      ConnectionFailed and DBSelectionFailed exceptions, to preserve
      the state of Connection::errnum() at the point of the exception,
      so you don't have to rely on this value remaining unchanged
      during the exception throw process.  All places that use these
      exceptions now include this value where possible.  Thanks for the
      initial patch go to Jim Wallace.

    o Removed Lockable mechanism from Connection and Query; it was
      conceptually flawed.  See the new user manual chapter on
      threading for advice on using MySQL++ safely without locking.
      There is mutex locking now in ConnectionPool, but that's it.

    o Connection::query() now takes an optional query string, allowing
      the returned Query object to start off with a value.  Especially
      useful when the query string is static, either because it's
      a simple query or because it's a template.  You can now build
      chains like "if (conn.query("CREATE INDEX ...").exec()) { ..."

    o Added Connection::thread_aware(), thread_end(), thread_id()
      and thread_safe().  See user manual's threading chapter for
      explanations.

    o Renamed "success" data members in Connection, Query and
      SimpleResult (neé ResNSel) to "copacetic_", making them private
      if they weren't before.  This better reflects their actual
      use, which isn't to say that there has necessarily been actual
      success, but rather that everything's okay with the object.

    o Removed success() member functions from above classes.  All can
      be tested in bool context to get the same information.

    o Replaced all operator bool()s in MySQL++ classes with safer
      alternatives.  See http://www.artima.com/cppsource/safebool.html
      Thanks to Jonathan Wakely for much helpful commentary, advice,
      and code used in these mechanisms.

    o Decoupled Connection::copacetic_ from Connection::is_connected_.
      It is now possible for the object to be copacetic without being
      connected.  However, if it tries to connect and fails, then
      it is not copacetic.  If it is copacetic and not connected, it
      means we haven't even tried to connect yet, a useful distinction.

    o Collapsed Connection's host, port, and socket_name down into
      a new combined 'server' parameter which is parsed to determine
      what kind of connection you mean.  These interfaces are still
      compatible with v2.3 and earlier up through the port parameter.
      There are differences beyond this.

    o Added TCPConnection, UnixDomainSocketConnection and
      WindowsNamedPipeConnection subclasses for Connection giving
      simpler construction and connect() method interfaces for
      instances where you know what kind of connection you want at
      compile time.

    o Changed Connection::ping() return value from int to bool.

    o Renamed NullisNull to NullIsNull -- capital I -- and similar for
      NullisZero and NullisBlank.

    o It's now a compile-time error to try to convert a MySQL++
      representation of a SQL null to any other data type, rather
      than a run-time error as in previous versions.  Removed
      BadNullConversion exception as a result.

    o Way back in v1.7.x we used the BadQuery exception for all kinds
      of exceptional conditions, not just bad queries.  Replaced
      most of these in v2.0.0 with new dedicated exceptions, but a
      few remained:
      
      - Errors that occur during the processing of a "use" query after
        the query itself executes correctly now throw UseQueryError.
        It's not a "bad query", because the query executed
        successfully.  It just choked during subsequent processing,
        so it's a different exception.  Thanks for this patch go to
        Jim Wallace.

      - Replaced BadQuery exceptions thrown in Row constructor due
        to bad ctor parameters with new ObjectNotInitialized exception
        This is also Jim Wallace's work.

    o The examples now all use getopt() type command line options
      instead of positional options.  This makes it possible to
      pass options in any order, leave at their default options that
      used to be in the middle of the sequence, and offer different
      subsets of options for different programs.  Also allows for
      special internal-use options, like -D passed by dtest to let
      examples change their behavior when run under dtest to produce
      only predictable output.

    o Split old libutil functionality into two modules, one holding
      all the "print data" functions, and another holding all the
      command line parsing stuff.  This makes it easier for newbies
      to ignore the command line stuff, treating it like a black box.
      The wish to understand the "print data" routines is much more
      common, so the two needed to be disentangled.

    o Renamed examples' libutil to libexcommon.

    o Removed connect_to_db() libutil function.  It combined command
      line parsing, which users don't care about, with database
      connection establishment, which they do care about.  Now the
      examples just call out to libexcommon to parse the command
      line, and use the values they get back to explicitly make the
      connection, so it isn't hidden.

    o Removed cchar and uint typedefs.

    o Redesigned dbinfo example's output to be easier to read.

    o Fixed an output formatting bug created in 2.3.0 that caused the
      tabular output from examples to not line up.

    o Renamed examples/tquery.cpp to tquery1.cpp.  Created tquery2.cpp
      to demonstrate passing parameters via a SQLQueryParametrs object
      instead of discretely.  Created tquery3.cpp for testing unquoted
      template parameters, such as integers.

    o Renamed fieldinf1.cpp example to fieldinf.cpp, and simplified
      its output so it can be part of the dtest sequence.

    o Renamed examples/xaction.cpp to transaction.cpp.  It created too
      much cognotive dissonance whenever thinking about both it and
      lib/transaction.cpp.

    o Added examples/deadlock.cpp, to test handling of exceptions due
      to server-side transaction deadlock detection.  Also added
      code to resetdb to create a table needed to test this.
      Initial version created by Jim Wallace to test the value of
      all his BadQuery exception work, with reworking by me.

    o Greatly expanded dtest suite.  Primary change is that we now
      have a handful of unit tests, where in v2.3.2 we only tested
      a subset of the examples.  Still very low coverage ratio,
      but it's a big improvement.

    o Optimized #includes, especially in lib/*.h to reduce
      dependencies and thus compile time when one of these changes.

    o Fixed a typo in RPM filename generation that prevented -devel
      RPM from recognizing that the corresponding MySQL++ library
      RPM was installed.

    o RPM spec file improvements by Remi Collet.

    o Renamed NO_LONG_LONGS to MYSQLPP_NO_LONG_LONGS to avoid a risk
      of collision in the global macro namespace.
    
    o First cut at Xcode2 project support.  Testing needed!

    o Debug build of library on VC++ and Xcode have a _d suffix now
      so you can have both versions of the library installed without
      conflict.

    o Moved the VC++ 2003 project files into a new vs2003 subdirectory
      because there are so many of them.  Also created vs2005
      subdirectory for VC++ 2005 and 2008 compatible project files.
      2005 makes an even bigger mess of the directory containing
      the .sln file, so the incentive is bigger.  Plus, we have to
      disable several things to get VC++ 2003 to build MySQL++ now,
      so we need a special 2005+ version of the project files for a
      complete build, if the user has one of the newer compilers.

    o ...plus dozens of small bug fixes and internal enhancements,
      many documentation improvements, and expansion of support for
      newer operating systems and compilers.


2.3.2, 2007.07.11 (r1669)

    o Previous release's const_string change caused more problems
      than it fixed.  This release contains the real fix. :)

    o New Connection::set_option() handling deals with the multi
      statements option correctly again.  examples/multiquery now
      runs again as a result.

    o Added new unit testing script, called dtest.  See the
      HACKERS file for details.  (This tool caught the previous
      two problems!)

    o Squished a GCC pedantic warning.  Thanks for the patch go to
      Andrew Sayers.


2.3.1, 2007.07.10 (r1659) The "After the Fireworks" release

    o const_string objects now keep a copy of their data, not
      just a pointer to it.  This is less efficient, but necessary
      to allow SSQLS to work with BLOBs.  Without this, we were
      seeing segfaults due to accessing freed memory pointed to
      by the const_string, because the underlying object went
      out of scope.

    o Fixed many more potential embedded null handling problems
      in manip.h.

    o MySQL++ can now optionally reference MySQL C API headers as
      being in a mysql subdirectory, a common thing on *ix systems,
      by defining MYSQLPP_MYSQL_HEADERS_BURIED before #including
      mysql++.h.

    o Restored ColData_Tmpl<T>::get_string(), removed in v2.3.0,
      along with warnings in the docs saying why you don't want
      to use it, and what your alternatives are.

    o VC++ and MinGW builds now define the HAVE_MYSQL_SSL_SET
      macro, which lets you use the C API's SSL features.
      This assumes your C API library does actually have these
      features enabled, which is the case with the official binary
      releases on Windows.  (Builds on *ix systems continue to
      test for these features at configure time.)

    o Fixed simple examples-only Makefile generation, for RPMs.


2.3.0, 2007.07.02 (r1645)

    o Added Query::for_each() and Query::store_if() methods
      proposed by Joel Fielder, and added examples for each.

    o It's now possible to store BLOB data in an SSQLS.  It's not
      foolproof, so added a section to the user manual (5.9) to
      document the method.  Also, changed examples/cgi_jpeg to use
      this new mechanism, instead of the ugly "raw row data" method
      it used to use.

    o Revamped Connection::set_option() handling.  These options
      used to be queued up, and applied only just before actually
      establishing the connection.  This made error reporting less
      helpful because the diagnostic was separated from the cause.
      Plus, the error messages were misleading to begin with.  Now,
      set_option() takes effect immediately if the connection is not
      yet up (excepting one special option that can actually be set
      after the connection is up) and issues better diagnostics when
      it detects errors.

    o Connection::connect() used to set a few options in such a
      way that the user couldn't override them.  Now it's smart enough
      to set them with the desired default values only when we see
      that the user hasn't given them other values.

    o SQLString can now be initialized from a mysqlpp::null,
      giving a "NULL" string.  This is useful for template queries.
      Patch by Michael Hanselmann.

    o resetdb error message about mixing library and header version
      numbers is now more explicit.

    o Changed BadConversion exception's "what" message text to be
      more like the other exceptions.  The inconsistency lead one
      to incorrectly copy-paste code from another exception handler,
      expecting it to behave the same way.  Now it does.

    o Added Row::raw_size(), as a shortcut for Row::at().size().

    o ssqls-pretty now detects when it's being run from within
      the MySQL++ distribution tree and gives a different -I flag
      to the compiler, so that it picks up the distribution headers
      instead of those that may be on the system already.

    o The quote manipulator now works for char[] correctly.
      Thanks for this patch go to Andrew Sayers.  (It's always
      worked for char*, but C++ doesn't consider that to be the
      same type, so it used the generic quote handling path,
      which doesn't do anything for char[].)

    o Fixed a build bug on older Solaris versions where the
      test for the C API library was erroneously failing, stopping
      the configuration process.

    o Simplified mysql_shutdown() level argument detection.
      Already had to do a version number ifdef check for the
      Windows case, so there's really no point to doing it with
      autoconf on Unixy platforms.  Moved version number check
      into lib/connection.cpp, and nuked the separate autoconf and
      Windows tests.

    o Removed dependency of sql_types.h on myset.h and (indirectly)
      datetime.h.  Now we only define sql_* typedef aliases for those
      MySQL++ types if the headers are included before sql_types.h.

    o Fixed a typo in one of the storein_sequence() template
      overloads, which is apparently rarely (or never?) used, because
      no one reported the compiler error you'd get if you tried.

    o Fixed a few more embedded null handling problems.

    o ColData used to keep two copies of all data it held.
      Now it keeps just one.

    o Fixed install.bat script to track the unified Bakefile change
      and the lack of separate debug and release builds under MinGW.

    o Yet another STLport + Query memory leak fix.

    o Squished a warning in newer GCCs having to do with identifier
      shadowing.  Patch by Jonathan Wakely.

    o Fixed a null-termination bug in Query::parse().  If you
      somehow constructed a query string without a terminating null
      character, then tried to parse it as a template query, it could
      walk off the end of the string.  Patch by Worster Chen.

    o Removed MYSQLPP_EXPORT tag from FieldNames and FieldTypes
      class declarations, as this can cause problems in programs
      that use vector<string> in VC++.  It has to do with multiply
      defined templates, since these classes derive from that
      template, and VC++ can't resolve the conflict without help.
      Since these classes aren't actually used outside the library,
      this shouldn't cause a problem.  Patch by Nils Woetzel.

    o Partial fix to Doxygen PDF build on RHEL4 and 5.  Needs
      hand-coaxing to complete successfully on RHEL4, and doesn't
      yet work at all on RHEL5.

    o Shortened the "no*" options to the bootstrap script, so that
      the usage message fits on a single line.

    o Added "nodoc" bootstrap script option, for disabling the
      documentation build during the dist target build.  Allows for
      building binary RPMs on CentOS 5.0, where doc building is
      currently broken.

    o Removed the updel example program.  It was kind of silly,
      and if you were to rewrite it today, you'd use for_each() anyway.

    o Lots of documentation improvements.


2.2.3, 2007.04.17 (r1538) The "Tax Day" release

    o Previous version left examples/vstudio/* out of the tarball
      by accident.

    o Improved generation of RPM temporary build directory path
      name generation.  Was using a hacked variant of the Fedora
      Packaging Guidelines' second best choice.  Now we're using
      the choice they recommend most highly, without changes.

    o Removed unnecessary resources from vstudio/wforms example.

    o Minor URL fix in refman


2.2.2, 2007.04.13 (r1526) The "Nervousmaking Friday the 13th" release

    o More small fixes to embedded null handling in Query.

    o Fixed a bug in single-parameter template query handling.

    o Added tquery example, to demonstrate proper use of template
      queries.  Previously, resetdb was the only exemplar, and
      it wasn't really suited for that.  This example also tests
      the previous item.

    o Added examples/vstudio/mfc, allowing us to improve the way
      we demonstrate Unicode handling.  Old way wasn't realistic.
      On *ix, people will depend on the terminal code to handle
      UTF-8.  On Windows, users are almost certain to be writing
      a GUI program, which requires different Unicode handling
      than the old examples showed.

    o Removed explicit Unicode conversion stuff from command line
      examples, and reworked the Unicode chapter in the user
      manual.
    
    o Added examples/vstudio/wforms to show integration with
      C++/CLI and Windows Forms.  Documented this in README.vc.

    o Rewrote load_file and cgi_image examples to be more
      useful, renaming them to load_jpeg and cgi_jpeg along
      the way.  Also, resetdb now creates a second table in the
      sample database for these two examples' use.  Also, added
      examples/logo.jpg to the distribution as sample data for
      these examples.

    o Limited the ostream base class casting stuff in Query to
      VC++ 2003, which is the only platform that really needed it.
      VC++ 2005 emits a warning with that hack in place, and on
      other platforms it's just replicating work that the compiler
      does already.

    o Added library version information to main library target
      so that systems that version shared libraries work as
      expected.  Thanks for this patch go to Jack Eidsness.

    o Merged much of the diffs between Remi Collet's RPM spec file
      into the official one.

    o Reorganized the doc subdir a bit.  Generated HTML is now all
      under doc/html instead of scattered under other subdirs,
      and renamed doc/README.mysql++ to doc/README.manuals.

    o Improvements to top-level manual building make targets:
      manuals now only rebuild at need, it's easier to request
      a rebuild of all manuals, and we force a rebuild attempt
      before building the distribution tarball so we don't ship
      outdated manuals.

    o Added ability to run examples under gdb using exrun,
      using same mechanism as we currently have for valgrind.
      Thanks for this patch go to Michael Hanselmann.

    o Added "Important Underlying C API Limitations" chapter to the
      user manual, to cover problems we keep seeing on the
      mailing list that are the result of ignorance of the way
      libmysqlclient behaves, not bugs MySQL++ is really in a
      position to fix.


2.2.1, 2007.02.28 (r1433)

    o Fixed the new localtime() alternative selection code
      for VS2003 and various uses of STLport.

    o No longer inserting a null character into the query stream
      on calling one of the preview() functions.  This was harmless
      in v2.1, which used C strings more extensively, but began
      causing problems in v2.2 due to its wider use of C++ strings.

    o Fixed a bug in the Connection copy ctor where it didn't
      completely initialize the object.

    o Optimized Query::preview_char() a bit.  Patch by Jonathan
      Wakely.

    o Reordered directory list used by autconf when locating the
      MySQL C API library.  The list is now ordered with the
      most likely locations for the library first, so we're less
      distracted by incorrect libraries.  This fixes a specific
      build error under RHEL4 with recent versions of MySQL 5.0.


2.2.0, 2007.01.23 (r1417)

    o ColData, const_string, and SQLString can now be constructed
      with an explicit length parameter.  Furthermore, Query
      class's execute(), store() and use() call chains terminate
      in a version taking an explicit length parameter, instead
      of one taking a simple C string.  Together, this means
      that it's now easier to handle data from the SQL server
      containing nulls.  The library is almost certainly not yet
      capable of handling embedded nulls in all cases, but this
      is a big first step towards that.

    o Can now construct a DateTime object from a time_t, and
      convert a DateTime back to a time_t.  Patch by Korolyov Ilya.

    o Changed the way we're handling exported functions in the
      Windows DLL case so that it works more reliably under MinGW.

    o Added proper copy semantics to Connection, so that you get a
      new connection with the same parameters, not just a bitwise
      copy of the object.

    o Using an explicitly thread-safe variant of localtime() for
      time conversions where one is available.

    o Removed ListInsert template from myset.h.  This wasn't used
      within the library, and was never documented, so I'm betting
      that no one actually uses it.

    o Result::copy() was not copying the exception flag in
      all cases.  Fix by Steven Van Ingelgem.

    o Added exrun shell script and exrun.bat files to distribution,
      to avoid linkage errors when running the examples while
      you still have an older version of MySQL++ installed.

    o Renamed MYSQLPP_LIB_VERSION to MYSQLPP_HEADER_VERSION, as
      what it really encodes is the version number in the mysql++.h
      file you're using, not the actual library version number.

    o Added mysqlpp::get_library_version(), which returns the
      library version number at build time.  Between this and
      the header version constant, you can check that you're not
      mixing MySQL++ header and library versions.

    o resetdb example uses these new version number affordances to
      double-check that you're not mixing libraries and headers
      from different versions.  This happens easily unless you
      take care of it (such as by using exrun) when you have one
      version of MySQL++ installed and you're trying to build and
      test a new version without blowing away the old one first
      or overwriting it.

    o No longer using recursive Makefiles on Unixy platforms
      or split lib + examples project files on VC++.  Everything is
      handled by a single top-level Makefile or project file, which
      is simpler for the end user, and makes better dependency
      management possible.

    o When looking for the MySQL C library on systems using
      autoconf, looking in .../lib64 wherever we are also looking
      in .../lib.

    o RPM build process no longer depends on Bakefile.  It means
      you have to build the examples when building an RPM even
      though they're never used within the RPM, but it's a better
      tradeoff in my opinion.

    o Updated include and library paths on Windows to reflect
      changes in the most recent MySQL installers.

    o Merged lib/defs.h and lib/platform.h into new file,
      lib/common.h.  Just cleans up the library internals.

    o Fixed build errors on Windows due to recent changes in MySQL.

    o Fixed a few memory leaks and double-deletes in Query class.

    o Fixed compatibility with STLPort's string implementation.
      Patch by dengxy at cse.buaa.edu.cn.

    o Fixed a compatibility problem between Set<> template and
      SSQLS.  Patch by Korolyov Ilya.

    o Fixed build bug in SQLQueryParms due to a character
      signedness issue on PowerPC with GCC.  Patch by Michael
      Hanselmann.

    o ~Transaction() can no longer throw exceptions.  It'll just
      quietly eat them, to avoid program termination.  Fix
      suggested by Alex Burton.

    o Fixed thread safety testing in autoconf case, accidentally
      broken during v2.1.0 development cycle.

    o Using Doxygen 1.5.1 to generate documentation.


2.1.1, 2006.04.04 (r1289)

    o MinGW and Cygwin will now build and link to mysqlpp DLLs.

    o Fixed bug in Query, causing it to initialize the "throw
      exceptions" flag incorrectly.  Thanks for this patch go to
      Joel Fielder.

    o Added -v flag for custom.pl script, which turns off the
      multiply-defined static variable fix.  Needed for VS 2003,
      which doesn't support variadic macros.  Also, added
      a diagnostic to detect the need for the -v flag, and
      suppressed the test for this feature in examples/util.cpp.


2.1.0, 2006.03.24 (r1269)

    o Converted automake and makemake files to their equivalents in
      Bakefile format.

    o Added the Transaction class, which makes it easy to use
      transaction sets in MySQL++.

    o Added xaction example to test new Transaction class.

    o Resetdb example now creates its example table using the
      InnoDB storage engine, in order to test the new transaction
      support.  Resetdb also declares the table as using UTF-8
      text; this doesn't change anything, but it does correctly
      document what we're doing.

    o Added sql_types.h header, containing C++ typedefs
      corresponding to each MySQL column type.  Using those new
      types in the type_info module, and in the SSQLS examples.

    o Replaced the way we were handling the template query
      version of Query member functions, to allow an arbitrary
      number of template query parameters.  By default, we
      now support 25 parameters, up from the old limit of 12.
      It's now possible to change just one number, run a script,
      and have a new limit.

    o Connection class does a better job of returning error
      messages if you call certain member functions that depend
      on a connection to the server before the connection is
      established.

    o Updated libmysqlclient.def for newer versions of MySQL.  (Fixes
      build errors having to do with mysql_more_results() and
      mysql_next_result().

    o Replaced final use of strcpy() with strncpy().

    o custom.pl now runs without complaint in strict mode, with
      warnings turned on.  Thanks for this patch go to "Waba".

    o Fixed a bug in custom.pl where incorrect code would be
      generated for some SSQLS set() methods.  Thanks for this
      patch go to "Waba".

    o SSQLS structures now support long and unsigned long fields.
      Thanks for this patch go to "Waba".

    o It's now possible to put SSQLS definitions in a header
      file used by multiple modules in a program without
      getting multiple static member definition errors.  See the
      documentation for details.  Thanks for this patch go to
      Viktor Stark.

    o Moved the definition of the 'stock' SSQLS out of the
      custom*.cpp example files and into a new stock.h file.
      Also, #including that file in the util module to test out
      the new SSQLS multiple static definition fix.

    o Using all of the digits of precision guaranteed by the
      IEEE 754 spec when stringizing floating point numbers
      to build queries.  Previously, we would use the platform
      default, which can be as few as 6 digits.

    o Removed lib/compare.h.  Not used within the library, never
      documented, and nobody seems to want to defend it.


2.0.7, 2005.11.23 (r1147)

    o Added explicit mysqlpp namespace qualifiers to generated code in
      custom*.h so you can use SSQLS in places where it doesn't make
      sense to say "using namespace mysqlpp" before the declaration.
      Also updated some of the examples to not have this "using"
      declaration to make it clear to users that it isn't needed, if you
      want to use explicit namespace qualifiers as well.  Thanks for
      this patch to Chris Frey.

    o Removed an apparently useless unlock() call from ResUse; there is
      no nearby lock() call, so if this unlock() is in fact necessary,
      it shouldn't be here anyway, because the two calls should be
      nearby each other.  Thanks for this patch to Chris Frey.

    o Fixed Query ostream initialization bug affecting SunPro CC (at
      least).  While this bug violates the Standard, it doesn't affect
      many real compilers because they don't enforce this rule.  Fixed
      by Chris Frey.

    o Previously, we only used the C99 style "long long" support when
      building under GNU CC.  This is now the default.  This should
      allow the code to work under SunPro CC.

    o Added another dynamic cast needed for proper Query ostream
      subclass overloading under VC++.  (7.1 at least...)

    o Detecting whether MySQL is built with SSL support on platforms
      using autotools.  Needed on some old Sun systems, for instance.
      Thanks for this patch to Ovidiu Bivolaru.

    o Fixed a potential memory bug in ColData's conversion to SQL null.

    o Many minor packaging tweaks.  (README clarifications, file
      permission fixes, better adherence to GNU packaging standards,
      etc.)

    
2.0.6, 2005.09.28 (r1123)

    o Fixed makemake.bat so it works on cmd.exe, not just 4NT.

    o Documentation fixes.


2.0.5, 2005.09.13 (r1114)

    o Visual C++ build now requires GNU make.  It is tested to work
      with either the Cygwin or the MinGW versions.  The previous
      version of MySQL++ used nmake.  This change enabled the
      following features:

        o Debug and Release versions are both built into
          separate subdirectories.

        o Dependency tracking for release version works
          correctly now.  (Previously dependencies worked
          only for debug version.)

        o 'make clean' removes release version binaries
          in addition to debug versions.

    o MinGW makemake support updated to support new release/debug
      subdirectory system.  This is probationary support, since
      this code currently can't be built as a DLL.  As a result,
      it is no more useful than the Cygwin version, for licensing
      reasons.

    o Several fixes to allow building on Solaris 8.  These fixes may
      also help on other SVR4-derived systems.

    o Removed Borland C++ makemake support, because this version
      of the library does not work completely, and there seems
      to be almost no user interest in fixing it.
      
    o Clarified "Handling SQL Nulls" section of user manual's
      Tutorial chapter.


2.0.4, 2005.08.29 (r1076)

    o Made mysql_shutdown() second parameter autoconf check less
      sensitive to compiler pedantry.

    o VC++ library Makefile is now smart enough to re-create the
      import library, if it is deleted while leaving the DLL alone.

    o Added libmysqlclient.def to tarball.

    o Reworked most of the top-level README* files.

    o Renamed LGPL file to LICENSE.


2.0.3, 2005.08.25 (r1060)

    o Visual C++ makemake system updated to build both debug and
      release versions of library DLL.

    o Fixed bug in simple1 example that caused crashes on Windows.

    o Doing UTF-8 to ANSI text translation in simple examples now.

    o Previous two releases built libmysqlpp with wrong soname on
      autotools-based systems.  Fixed.


2.0.2, 2005.08.18 (r1050)

    o Fixes to makemake system for cmd.exe.

    o Fixed the case where the system's C++ library includes an slist
      implementation in namespace std.


2.0.1, 2005.08.17 (r1046)

    o Added new simple1 example, showing how to retrieve just one
      column from a table.  Old simple1 is now called simple2, and
      simple2 is likewise shifted to simple3.

    o Added custom6 example, showing how to do the same thing with
      SSQLS.

    o Updated user manual to cover new examples.

    o Was accidentally shipping Subversion crap with tarball.  Fixed.


2.0.0, 2005.08.16 (r1031) The "Excess Hair Removal" release

    THIS IS NOT A DROP-IN REPLACEMENT FOR MySQL++ v1.7!

    At minimum, you will have to recompile your program against
    this library.  You may also have to make code changes.
    Please see the "Incompatible Library Changes" chapter of
    the user manual for a guide to migrating your code to this
    new version:

        http://tangentsoft.net/mysql++/doc/html/userman/breakages.html

    o The library's shared object file name (soname) scheme has
      changed.  (This mainly affects POSIX systems.)
      
      The soname for the last 1.7.x releases of MySQL++ was
      libmysqlpp.so.4, meaning the fourth version of the library's
      application binary interface (ABI).  (The first ABI version
      in this scheme was that provided by 1.7.9.)  MySQL++
      2.0.0's soname is libmysqlpp.so.2.0.0.  Since the dynamic
      linker setup on some systems will create a symlink to
      that file called libmysqlpp.so.2, it's possible that this
      library could be confused with that for MySQL++ 1.7.19
      through .21, which also used this number.  Do not install
      this library on a system which still has binaries linked
      against that version of the library!

      The new scheme is {ABI}.{feature}.{bug fix}.  That is,
      the first number changes whenever we break the library's
      binary interface; the second changes when adding features
      that do not break the ABI; and the last changes when the
      release contains only internal bug fixes.  This means
      that we will probably end up with MySQL++ 3.0 and 4.0 at
      some point, so there will be further soname conflicts.
      Hopefully we can put these ABI changes off long enough
      to avoid any real problems.

    o autoconf now installs headers into $prefix/include/mysql++,
      instead of $prefix/include.  If you were using the
      --includedir configure script option to get this behavior
      before, you no longer need it.

    o Linux binary RPMs will henceforth include only the
      libmysqlpp.so.X.Y.Z file, and create any short names
      required, to allow multiple versions to be installed at
      once.  Currently, you cannot install two MySQL++ library
      RPMs at once, because they both have /usr/lib/libmysqlpp.so.X,
      for instance.

    o Replaced the Visual C++ and Borland C++ project files with
      a new "makemake" system, which creates Makefiles specific
      to a particular toolchain.  This new mechanism also supports
      MinGW and generic GCC-on-*ix.  This was done partly to reduce
      the number of places we have to change when changing the
      file names in MySQL++ or adding new ones, and partly so we're
      not tied to one particular version of each of these tools.

    o VC++ Makefiles create a DLL version of the library only
      now, so there's no excuse for LGPL violations now.
      This same mechanism should make DLL builds under other
      Windows compilers easy.

    o Added Connection::enable_ssl(), which enables encrypted
      connections to the database server using SSL.

    o Connection::create_db() and drop_db() now return true on
      success, not false.

    o Connection::create_db() and drop_db() use Query::exec()
      now, for efficiency, rather than Query::execute().

    o Removed Connection::infoo().  Apparently just there to
      save you from a typo when calling the info() method, since
      it was a mere alias.

    o Renamed Connection::real_connect() to connect(), gave
      several more of its parameters defaults, and removed old
      connect() function.  Then changed user manual and examples
      to use new APIs.

    o Replaced Connection::read_option() with new set_option()
      mechanism.  The name change matches the method's purpose
      better.  Functional changes are that it returns true on
      success instead of 0, it supports a broader set of options
      than read_option() did, and it enforces the correct option
      argument type.

    o You can now call Connection::set_option() before the
      connection is established, which will simply queue the option
      request up until the connection comes up.  If you use this
      feature, you should use exceptions, because that's the only
      way an option setting failure can be signalled in this case.

    o Removed query-building functions (exec*(), store*(),
      use()) from class Connection, and moved all the implementation
      code to class Query.  Query no longer delegates the final
      step of sending the query to the database server to
      Connection().

    o Added Connection::enable_ssl(), for turning on SSL support on
      a connection.

    o Extracted exception disabling mechanism out of the many
      classes that had the feature into a new OptionalExceptions
      base class, which all classes having this feature now
      derive from.  Also, removed all per-method exception
      handling flags.  Finally, added NoExceptions class.  With
      all of these changes, there is now a common way to disable
      exceptions with fine granularity on all objects that
      support the feature.

    o All custom MySQL++ exceptions now derive from the new
      Exceptions class.  This regularizes the exception interface
      and allows you to use a single catch() block if you want.

    o The "throw exceptions" flag is passed from parent to child
      in all situations now.  (Or if not, please report it as
      a bug.) This fulfills a promise made in the v1.7.9 user
      manual, with the cost being that some programs will see
      new exceptions thrown that they're not expecting.

    o Added a bunch of new exception types: BadOption,
      ConnectionFailed, DBSelectionFailed, EndOfResults,
      EndOfResultSets, LockFailed, and ObjectNotInitialized.
      Some of these replace the use of BadQuery, which in v1.7.x
      was a kind of generic exception, thrown when something more
      specific wasn't available.  Beware, this means that programs
      may start crashing after recompiling them under v2.0 due to
      uncaught exceptions, if they were only trying to catch BadQuery.

      There are additional instances where the library will
      throw new exceptions.  One is when calling a method that
      forces the internals to use an out-of-bounds index on a
      vector; previously, this would just make the program
      likely to crash.  Another is that the library uses the
      BadFieldName exception -- created in v1.7.30 -- in more
      apropos situations.

    o Renamed SQLQueryNEParms to BadParamCount, to match naming
      style of other concrete exception types.

    o Extracted lock()/unlock() functions from Connection and
      Query classes into a new Lockable interface class.  Locking
      is implemented in terms of a different class hierarchy, Lock,
      which allows multiple locking strategies with a single ABI.

    o Removed ResUse::eof().  It's based on a deprecated MySQL
      C API feature, and it isn't needed anyway.

    o Removed arrow operator (->) for iterator returned by Fields,
      Result and Row containers.  It was inherently buggy, because
      a correct arrow operator must return the address of an
      object, but the underlying element access functions in these
      classes (e.g. at()) return objects by value, of necessity.
      Therefore, this operator could only return the address of
      a temporary, which cannot be safely dereferenced.

    o Returned Row subscripting to something more like the
      v1.7.9 scheme: there are two operator[] overloads, one for an
      integer (field by index) and another for const char* (field
      by name).  lookup_by_name() has been removed.  Because row[0]
      is ambiguous again, added Row::at() (by analogy with STL
      sequence containers), which always works.

    o Collapsed two of the Row::value_list*() overloads into
      two other similar functions using default parameters.
      This changes the API, but the removed functions aren't
      used within the library, and I doubt they are used outside,
      either.

    o Merged RowTemplate into Row.

    o Merged SQLQuery class into Query class.

    o Query is now derived from std::ostream instead of
      std::stringstream, and we manage our own internal string
      buffer.

    o Moved SQLParseElement and SQLQueryParms into their own
      module, qparms.

    o Added multiple result set handling to Query.  MySQL 4.1
      and higher allow you to give multiple SQL statements in a
      single "store" call, which requires extensions to MySQL++
      so you can iterate through the multiple result sets.  Also,
      stored procedures in MySQL 5.0 reportedly return multiple
      result sets.  Thanks for the initial patch go to Arnon Jalon;
      I reworked it quite a bit.

    o Query::storein*() now supports more varieties of the
      nonstandard slist comtainer.  (Singly-linked version of
      STL std::list.)

    o Template query mechanism and user manual had several
      mismatches.  Made manual match actual behavior, or
      made library match documented behavior, as apropriate.
      Initial patch by Jürgen MF Gleiss, with corrections and
      enhancements by Warren Young.

    o Collapsed mysql_* date and time base classes' methods and
      data into the subclasses.  Also, DateTime no longer derives
      from Date and Time; you could get away with that in the
      old hierarchy, but now it creates an inheritance diamond,
      and allows unsupported concepts like comparing a Time to
      a DateTime.

    o Removed "field name" form of Row::field_list().  It was
      pretty much redundant -- if you have the field names, why
      do you need a list of field names?

    o ColData can convert itself to bool now.  Thanks for this
      patch go to Byrial Jensen.

    o Removed simp_list_b type; wasn't being used, and doesn't
      look to be useful for end-user code.

    o Several methods that used to take objects by value now
      do so by const reference, for efficiency.

    o Several variable and function renamings so that MySQL++
      isn't needlessly tied to MySQL.  Even if we never make
      the library work with other database servers, there's
      little point in tying this library to MySQL blindly.

    o Renamed all private data members of MySQL++ classes to
      have trailing underscores.

    o 'private' section follows 'public' section in all classes
      now.

    o Removed mysql++.hh and sqlplus.hh backwards-compatibility
      headers.

    o Added copy ctors to Date/Time classes so that they will
      work in SSQLS under GCC 4.0.0.  Without these, the compiler
      couldn't make the conversion from raw MySQL row data.

    o Fixed a bunch of GCC 4.0 pedantic warnings: added virtual
      dtors to all base classes, calling base class ctors from leaf
      classes, etc.

    o All warnings fixed under VC++ at warning level 3.  (Mostly
      harmless signedness and integer conversion stuff.)

    o Updated LGPL license/copyright comments at the top of
      several files to use FSF's new physical address.

    o Relicensed user manual under a close variant of the Linux
      Documentation Project License, as it's designed for
      documentation, which the LGPL is not.  Permission for this
      received from Kevin Atkinson and MySQL AB.

    o Added ABI and API breakages chapter to user manual.  It
      is basically a subset of this ChangeLog, with only the
      information an end-user must know when migrating between
      versions.

    o Reworked user manual's DocBook code quite a bit after
      reading Bob Stayton's book "DocBook XSL" 3/e.  Better handling
      of stylesheets, taking advantage of some superior DocBook
      features, prettier output (especially the HTML version), etc.

    o Rewrote doc/userman/README to make it clearer how to get
      started contributing to the user manual.  It's essentially a
      "getting started with DocBook" guide now!

    o Lots of small text improvements to user and reference
      manuals.  Aside from the obvious tracking of library changes,
      made a bunch of minor style and clarity improvements.

    o Added CSS stylesheets for userman and refman to
      make the HTML versions of each a) not ugly; and b) match
      tangentsoft.net.  (Yes, some may say that these are incompatible
      goals....)

    o Standardized exception handling code in the examples that
      use it.

    o Fixed a potential memory leak due to exceptions thrown from
      ResUse.  Thanks for this patch go to Chris Frey.

    o Using new "no exceptions" feature of library in simple1
      example, so it is now truly simple.

    o simple1 example no longer depends as much on util module, so
      that all of the important code is in one place.  Makes
      learning MySQL++ a little less intimidating.

    o Added new simple2 and usequery examples, to demonstrate
      the proper way to handle a "use" query, with exceptions
      disabled, and not, respectively.  Added them to the user
      manual, in the appropriate place.

    o Refactored the "print stock table" example functions
      again, to make code using them clearer.

    o UTF-8 to UCS-2 handling in examples is now automatic on
      Windows.

    o Removed debug code from Windows Unicode output examples
      that slipped into previous release.

    o resetdb example is now clearer, and more robust in the
      face of database errors.

    o Simplified connect_to_db() in examples' util module.

    o Added sample autoconf macro for finding MySQL++ libraries, for
      people to use in their own autotools-based projects.

    o Lots and lots of minor cleanups not worth mentioning
      individually...


1.7.40, 2005.05.26 (r719)

    o Multiple item form of insert() now works if you're using the
      SQLQuery class, or its derivative, Query.  Thanks to Mark
      Meredino for this patch.

    o Fixed a bug in const_string::compare(), in which MySQL++
      would walk off the end of the shorter of the two strings.
      All was well if the two were the same length.

    o ResUse::operator=() now fully updates the object, so it's more
      like the behavior of the full ctor.

    o All source files now contain a license and copyright statement
      somewhere within them.

    o Optimized mysql++.h a bit: it now #includes only the minimum set
      of files required, and there is now an idempotency guard.
      This improves compile times a smidge, but mainly it was
      done to clean up the generated #include file graph in the
      reference manual.  Before, it was a frightful tangle because
      we #included everything except custom*.h.

    o Constness fix in MySQL++ date/time classes to avoid compiler
      warnings with SSQLS.  Thanks to Wolfram Arnold for this patch.

    o Fixed some compiler warnings in custom*.h.  Thanks to Chris Frey
      for this patch.

    o Added "Submitting Patches" and "Maintaining a Private CVS
      Repository" sections to the HACKERS file.  Thanks to Chris
      Frey for the source material for these sections.  The HACKERS
      file was improved in several other ways at the same time.

    o PDF version of user manual no longer has links to the reference
      manual.  They were ugly, and they were broken anyway due to the
      way we move the PDFs after generating them.  If you want
      interlinked manuals, use the HTML version.

    o PDF version of user manual now has hard page breaks between
      chapters.

    o Removed complic1 example.  Wasn't pulling its own weight.
      Everything it is supposed to demonstrate is shown in other
      examples already.

    o Refactored print_stock_table() in examples/util module to be
      four functions, and made all the examples use various of
      these functions where appropriate.  Before, several of
      the examples had one-off stock table printing code because
      print_stock_table() wasn't exactly the right thing, for one
      reason or another.  One practical problem with this is that
      some of the examples missed out on the recent Unicode updates;
      now such a change affects all examples the same way.

    o Since so many of the examples rely on the util module, the user
      manual now covers it.  The simple1 example in the user manual
      didn't make much sense before, in particular, because it's
      really just a driver for the util module.

    o Added custom5 example.  It shows how to use the equal_list()
      functionality of SSQLS.  Thanks to Chris Frey for the original
      version of this program.  (I simplified it quite a bit after
      accepting it.)

    o New user manual now covers the value_list(), equal_list() and
      field_list() stuff that the old manual covered but which was
      left out in previous versions of the new manaul.  Most of the
      examples are the same, but the prose is almost completely new.
      This new section includes the custom5 example.

    o Every declaration in MySQL++ is now documented in the reference
      manual, or explicitly treated as "internal only".

    o Improved docs for MySQL++'s mechanism to map between MySQL
      server types and C++ types.  Initial doc patch by Chris Frey,
      which I greatly reworked.

    o Improved a lot of existing reference manual documentation while
      adding the new stuff.

    o Expanded greatly on the exception handling discussion in the user
      manual.

    o Added all-new "Quoting and Escaping" section to the user
      manual's Tutorial chapter.  Moved some existing comments on
      quoting and escaping around and added some new ones to other
      sections as a result.

    o Added all-new "Handling SQL Nulls" section to the user manual's
      Tutorial chapter.

    o Many improvements to the Overview section of the user manual.

    o Row::operator[] reference now explains the right and wrong way to
      use the values it returns.  This is in response to a mailing list
      post where someone was incorrectly using this feature and getting
      a bunch of dangling pointers.

    o Updated Doxyfile so 1.3.19.1 parses it without warnings.  Still
      works with versions back to 1.2.18, at least.  (These are
      the versions shipped with Fedora Core 3 and Red Hat Linux 9,
      respectively.)

    o Using a superior method to make Doxygen ignore certain sections
      of the source code.  Between this change and the fact that
      everything not so ignored is documented, Doxygen no longer
      generates any warnings.

    o Lots of code style updates.  Everything should now be consistently
      formatted.


1.7.35, 2005.05.05 (r601) The "Cinco de Mayo" release

    o Added a "how to use Unicode with MySQL++" chapter to the user
      manual.  (Too bad "Cinco de Mayo" doesn't have any accented
      characters.  That would be just _too_ precious.)

    o VC++ examples now use the Unicode Win32 APIs, so they can display
      Unicode data from MySQL++.

    o Added an optional conversion function to examples/util.cpp to
      handle the conversion from UTF-8 to UCS-2 on Win32.

    o Moved "brief history of MySQL++" from intro section of refman to
      intro section of userman.

    o Lots of small bits of documentation polishing.
    
    o Made some minor constness fixes.  Thanks to Erwin van Eijk
      for this patch.

    o Made some warning fixes for GCC 4.0.  Not all warnings are
      fixed, because some of the needed changes would break the ABI.
      Thanks to Chris Frey for this patch.

    o Added lib/Doxyfile to distribution.
    

1.7.34, 2005.04.30 (r573)

    o Added a multiple-insert method for Query, which lets you insert
      a range of records from an STL container (or the whole thing,
      if you like) in a single SQL query.  This is faster, and it
      reduces coding errors due to less repetition.  Thanks to Mark
      Meredino for the patch.

    o Reference and user manual now get rebuilt automatically when
      required.  (E.g. on 'make dist', or explicitly now through 'make
      docs'.)

    o Made it easier to change the maximum number of SSQLS data members
      in generated custom-macros.h file.  It used to be hard-coded in
      several places in lib/custom.pl; now it's a variable at the top of
      the file.

    o Changed default SSQLS data member limit to 25, which is what it
      has been documented as for a long time now.  It was actually 26
      within custom.pl.

    o Fixed a regression in previous version.

    o Trimmed some fat from the distribution packages.

    o Some more small doucmentation improvements.


1.7.33, 2005.04.29 (r555)

    o Worked around an overloaded operator lookup bug in VC++ 7.1
      that caused SSQLS insert, replace and update queries to get
      mangled.  (Symptom was that custom2 and custom3 examples didn't
      work right.)  Thanks to Mark Meredino for digging up the
      following, which explains the problem and gives the solution:

      http://groups-beta.google.com/group/microsoft.public.vc.stl/browse_thread/thread/9a68d84644e64f15

    o Some VC++ warning fixes.

    o Major documentation improvements:
    
        o Using DocBook for user manual and Doxygen for reference
          manual.  The former now references the latter where
          useful.

        o Split out HACKERS and CREDITS files from main README,
          and improved remaining bits of README.

        o Moved the text from the old v1.7.9 LaTeX-based
          documentation over into the new systems, and reworked
          it to more closely resemble English.

        o Added a lot of new material to documentation, and
          simplified a lot of what already existed.

        o Documentation is now being built in HTML and PDF forms.

    o ebuild file updated to take advantage of recent configure script
      features.  Thanks to Chris Frey for this patch.



1.7.32, 2005.03.10 (r479)

    o Example building may now be skipped with --disable-examples
      configure script flag.

    o Changed stock items added in resetdb.  One is now UTF-8 encoded,
      to show that basic use of Unicode with MySQL++ is easy, yet not
      foolproof.  (See formatting of table on systems where cout isn't
      UTF-8 aware!)  Other stock items now follow a theme, for your
      amusement.  :)

    o custom3 example now changes UTF-8 item's name to the 7-bit ASCII
      equivalent.  Previously, this example would fix a spelling error
      in the table.

    o resetdb example now says 'why' when it is unable to create the
      sample database.

    o Small formatting change to print_stock_table(), used by several
      examples.

    o Was issuing a VC++-specific warning-disable pragma when built by
      any Windows compiler.  Fixed.
    

1.7.31, 2005.03.05 (r462) The "Inevitable Point-one Followup" release

    o Check for threads support must now be explicitly requested via
      configure script's new --enable-thread-check flag.

    o Fix for contacting MySQL server on a nonstandard port number.
      Thanks to Chris Frey for this patch.

    o Example programs using standard command line format now accept a
      fourth optional parameter, a port number for the server.  Thanks
      to Chris Frey for this patch.

    o One more g++ 3.4 pedantic warning fix by Chris Frey.

    o Exception handling in resetdb is no longer nested, because you'd
      get a segfault on some systems when an exception was thrown from
      one of the inner try blocks.

    o Improvements to Connection class's handling of locking mechanism.
      Concept based on patches by Rongjun Mu.

    o Implemented the declared-but-never-defined Query::lock().  Thanks
      to Rongjun Mu for this patch.
    
    o Cleaned up some unclear if/else blocks in connection.cpp by
      adding explicit braces, correct indenting and putting normal
      code path in the if side instead of the else.


1.7.30, 2005.02.28 (r443) The "Power of Round Numbers" release

    o bootstrap script now accepts a 'pedantic' argument, which sets a
      bunch of CFLAGS that make g++ very picky about the code it
      accepts without warnings.
      
    o Fixed a bunch of things that generated warnings with g++ in
      pedantic mode. Only two warnings remain, having to do with
      floating point comparisons.  (See Wishlist for plans on how to
      deal with these.)  Thanks to Chris Frey for this patch.

    o Split long tests out of configure.in into M4 files in new config
      subdir.  This makes configure.in easier to read.

    o Added preliminary thread support.  Currently, this just means that
      we detect the required compiler and linker thread flags, and link
      against the proper thread-safe libraries.  THERE MAY BE
      UN-THREAD-SAFE CODE IN MYSQL++ STILL!

    o Standard C++ exceptions are the default now.  Old pre-Standard
      exception stuff removed.

    o Row::lookup_by_name() will throw the new BadFieldName exception if
      you pass a bad field name.  Thanks for this patch to Chris Frey.

    o Row::operator[] will throw a Standard C++ out of bounds exception
      by way of std::vector::at() if you pass it a bad index.  Thanks
      for this patch to Chris Frey.

    o Setting Connection::is_connected flag to false on close().
      Previously, is_connected() would continue to return true after
      close() was called.

    o All number-to-string conversion ctors in SQLString class now use
      ostringstream to do the conversion.  Previously, we used
      snprintf(), which isn't available on all systems.  Also, we used a
      C99 format specifier for the "long long" conversion, which is also
      not available on all systems.  This new ostringstream code should
      be platform-independent, finally.


1.7.28, 2005.02.04 (r403)

    o --with-mysql* flags to configure script now try the given
      directory explicitly, and only if that fails do they try
      variations, like tacking '/lib' and such onto it to try and find
      the MySQL includes and libraries.  Thanks to Matthew Walton for
      the patch.

    o Finally removed sql_quote.h's dependence on custom.h, by moving
      the one definition it needed from custom.h to deps.h.  This will
      help portability to compilers that can't handle the SSQLS macros,
      by making that part of the library truly optional.


1.7.27, 2005.01.12 (r395)

    o configure check for libmysqlclient now halts configuration if the
      library isn't found.  Previously, it would just be flagged as
      missing, and MySQL++ would fail to build.

    o Added sql_string.cpp to VC++ and BCBuilder project files.

    o Removed Totte Karlsson's 'populate' example, which never made it
      into the distribution anyway.

    o Removed last vestiges of 'dummy.cpp'.

    o Renamed *.cc to *.cpp in BCBuilder project files.

    o Worked around a BCBuilder C++ syntax processing bug in row.h.


1.7.26, 2004.12.17 (r382)

    o Moved all of the SQLString definitions out of the header and into
      a new .cpp file, reformatted it all, and made the integer
      conversion functions use snprintf() or _snprintf() instead of
      sprintf().  Also, widened some of the buffers for 64-bit systems.

    o Using quoted #include form for internal library headers, to avoid
      some problems with file name clashes.  (The headers should still
      be installed in their own separate directory for best results,
      however.)  Thanks to Chris Frey and Evan Wies for the patch and
      the discussion that lead to it.

    o Removed unnecessary semicolons on namespace block closures.
      Thanks to Evan Wies for this patch.

    o Fixed namespace handling in the legacy headers mysql++.hh and
      sqlplus.hh.  Thanks to Chris Frey for this patch.

    o #including iostream instead of ostream in lib/null.h for
      broader C++ compatibility.  (This may allow MySQL++ to work on GCC
      2.95.2 again, but this is unconfirmed.)

    o Detecting proper mysql_shutdown() argument handling automatically
      in platform.h for the Windows compiler case instead of making the
      user edit the file.  Thanks to Evan Wies for this patch.
    
    o Fixed examples/Makefile.simple to use new *.cpp file naming.

    o Fix to Gentoo ebuild file's exception configure switch handling.
      Thanks to Chris Frey for this patch.

    o Rebuilding lib/custom*.h intelligently now, to avoid unnecessary
      recompiles after running bootstrap script.


1.7.25, 2004.12.09 (r360)

    o Yet more fixes to the --with-mysql-lib and --with-mysql-include
      flags.

    o Added DLLEXPORT stuff to platform.h, hopefully so that someone
      can figure out how to make VC++ make a DLL version of MySQL++.

    o Renamed *.cc to *.cpp.

    o Made 'set -> myset' change in VC++ project files.

    o Some style changes (mostly whitespace) in header files.


1.7.24, 2004.12.08 (r343)

    o Fixed the --with-mysql-lib and --with-mysql-include flags'
      behavior, and extended their search ability to handle one other
      common case.  (Fixed by Steve Roberts)

    o Fixes to put freestanding functions in namespace mysqlpp.  (They
      weren't in the namespace, while all the class member functions
      were.)  This required bumping the ABI version number to 4.
      
    o Renamed set module to myset, to avoid conflicts with Standard C++
      Library's set.h when MySQL++ headers were installed into one of
      the standard system include directories.

    o Renamed all the idempotency guards to make them consistent in
      style and unique to MySQL++.

    o Reformatted all of lib/*.cc.


1.7.23, 2004.11.20 (r333)

    o Query::reset() now empties the stored query string.  If you
      subsequently stored a longer query in the object, you'd overwrite
      the previous query, but otherwise the longer part of the previous
      one would stick out past the new query.

    o We now look to the NO_LONG_LONGS macro only to decide whether to
      fake 64-bit integer support using 32-bit integers.

    o 64-bit integer support under Visual C++ may be working now, using
      that platform's __int64_t type.  This has not been tested.

    o Removed 64-bit integer support for Codewarrior on Mac OS 9 and
      earlier.  OS X uses GCC, so it requires no special support.

    o Added MinGW detection in platform.h.
    
    o If you pass a flag (-X) to the examples that take the standard
      parameters (resetdb, simple1, etc.), it prints a usage message.
    
    o Better error handling in resetdb example, where errors are the
      most critical.  (If that one runs without errors, the others
      probably will, too, and you have to run that one first.)

    o resetdb now reports success, rather than succeeding silently.

    o Removed the code in sample1 example that duplicated util module's
      print_stock_table(), and called that function instead.

    o Moved the preview() calls in the example programs to before the
      query execution calls, because execution modifies the query.

    o All examples that take the standard command line parameters now 
      exit when connect_to_db() fails in one of the ways that don't
      throw an exception, rather than bulling onward until the next
      MySQL database call fails because the connection isn't up.

    o dbinfo example now takes the standard command line parameters.

    o Much better output formatting in dbinfo example.

    o Calling reset() where appropriate in the various example programs.
      Before, the programs may have worked, but not for the right
      reason.  This lead some people to believe that calling reset()
      was not necessary.

    o Fixed an incorrect use of row["string"] in complic1 example.

    o Lots of code style improvements to the examples.

    o Some VC++ type warnings squished.  Some remain.
    

1.7.22, 2004.11.17 (r302)

    o Applied patches by Zahroof Mohammed to allow it to build under GCC
      3.4.2.  Tested on MinGW and Fedora Core 3 systems.

    o Removed all the forward declarations in defs.h, and added
      forward declarations where necessary in individual header files.
      #including defs.h in fewer locations as a result.

    o Legacy headers sqlplus.hh and mysql++.hh now declare they are
      using namespace mysqlpp, to allow old code to compile against the
      new library without changes.

    o Removed query_reset parameter from several class Query member
      functions.  In the implementation, these parameters were always
      overridden!  No sense pretending that we pay attention to these
      parameters.  This changes the ABI version to 3.

    o #including custom.h in sql_query.h again...it's necessary on GCC
      3.4.
    
    o bootstrap script runs lib/config.pl after configure.  This is
      just a nicety for those running in 'maintainer mode'.


1.7.21, 2004.11.05 (r273)

    o Generating a main mysql++ RPM containing just the library files
      and basic documentation, and the -devel package containing
      everything else.

    o Devel package contains examples now, along with a new Makefile
      that uses the system include and library files, rather than the
      automake-based Makefile.am we currently have which uses the files
      in the mysql++ source directory.

    o Renamed sqlplusint subdirectory in the package to lib.

    o Removed the obsolete lib/README file.

    o lib/sql_query.h no longer #includes custom.h, simplifying
      build-time dependencies and shortening compile times.


1.7.20, 2004.11.03 (r258)

    o Collapsed all numbered *.hh headers into a single *.h file.  For
      example, the contents of row1.hh, row2.hh and row3.hh are now in
      row.h.

    o While doing the previous change, broke several circular
      dependencies.  (The numbered file scheme was probably partly done
      to avoid this problem.)  The practical upshot of most of these
      changes is that some functions are no longer inline.

    o Removed define_short.hh and everything associated with it.  The
      library now uses the short names exclusively (e.g. Row instead of
      MysqlRow).

    o Put all definitions into namespace mysqlpp.  For most programs,
      simply adding a 'using namespace mysqlpp' near the top of the
      program will suffice to convert to this version.

    o Once again, the main include file was renamed, this time to
      mysql++.h.  Hopefully this is the last renaming!

    o mysql++.hh still exists.  It emits a compiler warning that the
      file is obsolete, then it #includes mysql++.h for you.

    o sqlplus.hh is back, being a copy of the new mysql++.hh.  Both of
      these files may go away at any time.  They exist simply to help
      people transition to the new file naming scheme.

    o Renamed mysql++-windows.hh to platform.h, and added code to it to
      handle #inclusion of config.h on autotools-based systems
      intelligently.  This fixes the config.h error when building under
      Visual C++.

    o There is now only one place where conditional inclusion of
      winsock.h happens: platform.h.

    o Beautified the example programs.


1.7.19, 2004.10.25 (r186)

    o Fixed an infinite loop in the query mechanism resulting from the
      strstream change in the previous version.  There is an overloaded
      set of str() member functions that weren't a problem when query
      objects were based on strstream.
     
    o Query mechanism had a bunch of const-incorrectness: there were
      several function parameters and functions that were const for
      the convenience of other parts of the code, but within these
      functions the constness was const_cast away!  This was evil
      and wrong; now there are fewer const promises, and only one is
      still quietly broken within the code.  (It's in the SQLQuery
      copy ctor implementation; it should be harmless.)

    o Removed operator=() in Query and SQLQuery classes.  It cannot take
      a const argument for the same reason we have to cast away const
      in the SQLQuery copy ctor.  It's tolerable to do this in the copy
      ctor, but intolerable in an operator.  Since the copy ctor is good
      enough for all code within the library and within my own code, I'm
      removing the operator.

    o Above changes required bumping the ABI to version 2.

    o Visual C++ projects now look for MySQL build files in c:\mysql,
      since that's the default install location.  (Previously, it was
      c:\program files\mysql.)


1.7.18, 2004.10.01 (r177)

    o Changed all the strstream (and friends) stuff to stringstream type
      classes.  Let there be much rejoicing.

    o Query object now lets you use store() even when the SQL query
      cannot return a result, such as a DROP TABLE command.  This is
      useful for sending arbitrary SQL to the server.  Thanks to
      Jose Mortensen for the patch.

    o Quote fix in configure.in, thanks to David Sward.

    o Renamed undef_short file to undef_short.hh.

    o Gentoo ebuild file is actually being shipped with the tarball,
      instead of just sitting in my private CVS tree since 1.7.14 was
      current.  Ooops....


1.7.17, 2004.09.16 (r170)

    o Reverted one of the VC++ warning fix changes from 1.7.16 that
      caused crashes on Linux.

    o Added a configure test that conditionally adds the extra 'level'
      parameter to mysql_shutdown() that was added in MySQL 4.1.3 and
      5.0.1.


1.7.16, 2004.09.13 (r160)

    o Building VC++ version with DLL version of C runtime libraries, and
      at warning level 3 with no warnings emitted.

    o VC++ build no longer attempts to fake "long long" support.  See
      the Wishlist for further thoughts on this.


1.7.15, 2004.09.02 (r144)

    o Renamed Configure file to common.am, to avoid file name conflict
      with configure script on case-sensitive file systems.

    o Added ebuild file and ebuild target to top-level Makefile for
      Gentoo systems.  Thanks to Chris Frey for this.

    o Small efficiency improvements to BadQuery exception handling.
      Initial idea by Chris Frey, improvements by Warren Young.


1.7.14, 2004.08.26 (r130)

    o Builds with Visual C++ 7.1.

    o Fixed a bug in custom macro generation that caused problems with
      GCC 3.4.  (X_cus_value_list ctor definition was broken.)


1.7.13, 2004.08.23 (r92)

    o Removed USL CC support.  (System V stock system compiler.)  Use
      GCC on these platforms instead.

    o Added examples/README, explaining how to use the examples, and
      what they all do.

    o Most of the example programs now accept command line arguments for
      host name, user name and password, like resetdb does.

    o Renamed sinisa_ex example to dbinfo.

    o Several Standard C++ syntax fixes to quash errors emitted by
      GCC 3.4 and Borland C++ Builder 6.  Thanks to Steffen Schumacher
      and Totte Karlsson for their testing and help with these.

    o Added proper #includes for BCBuilder, plus project files for same.
      Thanks to Totte Karlsson for these.


1.7.12, 2004.08.19 (r63)

    o Many Standard C++ fixes, most from the GCC 3.4 patch by
      Rune Kleveland.

    o Added Wishlist file to distribution.

    o Fixed a problem in the bootstrap script that caused complaints
      from the autotools on some systems.

    o RPM building is working properly now.

    o Fixed the idempotency guard in datetime1.hh.


1.7.11, 2004.08.17 (r50)

    o Renamed mysql++, defs and define_short files, adding .hh to the
      end of each.  (They're header files!)  This shouldn't impact
      library users, since these are hopefully used internal to the
      library only.

    o Removed sqlplus.hh file.  Use mysql++.hh instead.
    
    o Added mysql++.spec, extracted from contributed 1.7.9 source RPM, 
      and updated it significantly.  Also, added an 'rpm' target to
      Makefile.am to automate the process of building RPMs.

    o Added bootstrap and LGPL files to distribution tarball.

    o Added pre-1.7.10 history to this file.

    o Removed .version file.  Apparently it's something required by old
      versions of libtool.


1.7.10, 2004.08.16 (r27)

    o Maintenance taken over by Warren Young (mysqlpp at etr dash usa
      dot com.) See http://lists.mysql.com/plusplus/3326 for details.

    o Applied many of the GCC 3.x patches submitted for 1.7.9 over
      the years.  This allows it to build on everything from 3.0 to
      3.3.3, at least.  Because so many patches are rolled up in one
      big jump, it's difficult to describe all the changes and where
      they came from.  Mostly they're Standard C++ fixes, as GCC
      has become more strict in the source code that it will accept.

    o MysqlRow used to overload operator[] for string types as well as
      integers so you could look up a field by its name, rather than by
      its index.  GCC 3.3 says this is illegal C++ due to ambiguities in
      resolving which overload should be used in various situations.
      operator[] is now overloaded only for one integer type, and a
      new member function lookup_by_name() was added to maintain the old
      by-field-name functionality.

    o Fixed another operator overloading problem in SSQLS macro
      generation with GCC 3.3.

    o The _table member of SSQLS-defined structures is now const char*,
      so you can assign to it from a const char* string.

    o Got autoconf/automake build system working with current versions
      of those tools again.  Removed the generated autotools files from
      CVS.

    o Renamed library file from libsqlplus to libmysqlpp.


1.7.9 (May 1 2001) Sinisa Milivojevic <sinisa@mysql.com>

    * Fixed a serious bug in Connection constructor when reading MySQL
    * options
    * Improved copy constructor and some other methods in Result /
    * ResUse
    * Many other minor improvements
    * Produced a complete manual with chapter 5 included
    * Updated documentation, including a Postscript format

1.7.8 (November 14 2000) Sinisa Milivojevic <sinisa@mysql.com>

    * Introduced a new, standard way of dealing with C++ exceptions.
    * MySQL++ now supports two different methods of tracing exceptions.
    * One is by the fixed type (the old one) and one is standard C++
    * type by the usage of what() method. A choice of methods has to be
    * done in building a library. If configure script is run with
    * -enable-exception option , then new method will be used. If no
    * option is provided, or -disable-exception is used, old MySQL++
    * exceptions will be enforced. This innovation is a contribution of
    * Mr. Ben Johnson <ben@blarg.net>
    * MySQL++ now automatically reads at connection all standard MySQL
    * configuration files
    * Fixed a bug in sql_query::parse to enable it to parse more then 99
    * char's
    * Added an optional client flag in connect, which will enable usage
    * of this option, e.g. for getting matched and not just affected
    * rows. This change does not require any changes in existing
    * programs
    * Fixed some smaller bugs
    * Added better handling of NULL's. Programmers will get a NULL
    * string in result set and should use is_null() method in ColData to
    * check if value is NULL
    * Further improved configuration
    * Updated documentation, including a Postscript format

1.7.6 (September 22 2000) Sinisa Milivojevic <sinisa@mysql.com>

    * This release contains some C++ coherency improvements and scripts
    * enhacements
    * result_id() is made available to programmers to fetch
    * LAST_INSERT_ID() value
    * Connection constroctur ambiguity resolved, thanks to marc@mit.edu
    * Improved cnnfigure for better finding out MySQL libraries and
    * includes
    * Updated documentation, including a Postscript format

1.7.5 (July 30 2000) Sinisa Milivojevic <sinisa@mysql.com>

    * This release has mainl bug fixes  and code improvements
    * A bug in FieldNames::init has been fixed, enabling a bug free
    * usage of this class with in what ever a mixture of cases that is
    * required
    * Changed behaviour of ResUse, Result and Row classes, so that they
    * could be re-used as much as necessary, without any memory leaks,
    * nor with any re-initializations necessary
    * Fixed all potential leaks that could have been caused by usage of
    * delete instead of delete[] after memory has been allocated with
    * new[]
    * Deleted all unused classes and macros. This led to a reduction of
    * library size to one half of the original size. This has
    * furthermore brought improvements in compilation speed
    * Moved all string manipulation from system libraries to
    * libmysqlclient, thus enabling uniformity of code and usage of 64
    * bit integers on all platforms, including Windows, without
    * reverting to conditional compilation. This changes now requires
    * usage of mysql 3.23 client libraries, as mandatory
    * Changed examples to reflect above changes
    * Configuration scripts have been largely changed and further
    * changes shall appear in consecutive sub-releases. This changes
    * have been done and shall be done by our MySQL developer Thimble
    * Smith <tim@mysql.com>
    * Changed README, TODO and text version of manual. Other versions of
    * manual have not been updated
    * Fixed .version ``bug''. This is only partially fixed and version
    * remains 1.7.0 due to some problems in current versions of libtool.
    * This shall be finally fixed in a near future
    * Several smaller fixes and improvements
    * Added build.sh script to point to the correct procedure of
    * building of this library. Edit it to add configure options of your
    * choice

1.7 (May17 2000) Sinisa Milivojevic <sinisa@mysql.com>

    * This is mainly a release dealing with bug fixes, consistency
    * improvements and easier configure on some platforms
    * A bug in fetch_row() method of ResUse class has been fixed. Beside
    * changes that existed in a distributed patch, some additional error
    * checking has been introduced
    * A bug in escape manipulator has been fixed that could cause an
    * error if all characters had to be escaped
    * An inconsistency in column indexing has been fixed. Before this
    * version, column names in row indexing with strings, i.e.
    * row[<string>] , has been case sensitive, which was inconsistent
    * with MySQL server handling of column names
    * An inconsistency in conversion from strings to integers or floats
    * has been fixed. In prior version a space found in data would cause
    * a BadConversion exception. This has been fixed, but 100%
    * consistency with MySQL server has not been targeted, so that other
    * non-numeric characters in data will still cause BadConversion
    * exception or error. As this API is used in applications, users
    * should provide feedback if full compatibility with MySQL server is
    * desired, in which case BadConversion exception or error would be
    * abolished in some of future versions
    * A new method in ColData class has been introduced. is_null()
    * method returns a boolean to denote if a column in a row is NULL.
    * Finally, as of this release, testing for NULL values is possible.
    * Those are columns with empty strings for which is_null() returns
    * true.
    * Some SPARC Solaris installations had C++ exception problems with
    * g++ 2.95.2 This was a bug that was fixed in GNU gcc, as from
    * release 2.95 19990728. This version was thoroughly tested and is
    * fully functional on SPARC Solaris 2.6 with the above version of
    * gcc.
    * A 'virtual destructor ' warning for Result class has been fixed
    * Several new functions for STL strings have been added. Those
    * functions (see string_util.hh) add some of the functionality
    * missing in existing STL libraries
    * Conversion for 64 bit integers on FreeBSD systems has been added.
    * On those systems _FIX_FOR_BSD_ should be defined in CXXFLAGS prior
    * to configuring. Complete conversion to the usage of functions for
    * integer conversion found in mysqlclient library is planned for one
    * of the next releases
    * A completely new, fully dynamic, dramatic and fully mutable result
    * set has been designed and will be implemented in some of 2.x
    * releases
    * Several smaller fixes and improvements, including defaulting
    * exceptions to true, instead of false, as of this version
    * An up-to-date and complete Postscript version of documentation is
    * included in this distribution
    * Large chunks of this manual are changed, as well as README and
    * TODO files.

1.6 (Feb 3 2000) Sinisa Milivojevic <sinisa@mysql.com>

    * This is a major release as it includes new features and major
    * rewrites
    * Automatic quoting and escaping with streams. It works
    * automatically , depending on the column type. It will work with <<
    * on all ostream derived types. it is paricularly handy with query
    * objects and strstreams. Automatic quoting and escaping on cout,
    * cerr and clog stream objects is intentionally left out, as quoting
    * / escaping on those stream objects is not necessary. This feature
    * can be turned of by setting global boolean dont_quote_auto to
    * true.
    * Made some major changes in code, so that now execute method should
    * be used only with SSQL and template queries, while for all other
    * query execution of UPDATE's, INSERT's, DELETE's, new method exec()
    * should be used. It is also faster.
    * New method get_string is inroduced for easier handling / casting
    * ColData into C++ strings.
    * Major rewrite of entire code, which led to it's reduction and
    * speed improvement. This also led to removal of several source
    * files.
    * Handling of binary data is introduced. No application program
    * changes are required. One of new example programs demonstrates
    * handling of binary data
    * Three new example programs have been written and thoroughly
    * tested. Their intention is to solve some problems addressed by
    * MySQL users.
    * Thorough changes is Makefile system has been made
    * Better configuration scripts are written, thanks to D.Hawkins
    * <dhawkins@cdrgts.com>
    * Added several bug fixes
    * Changed Manual and Changelog

1.5 (Dec 1 1999) Sinisa Milivojevic <sinisa@mysql.com>

    * Fixed bug in template queries, introduced in 1.4 (!)
    * Fixed connect bug
    * Fixed several bug in type_info classes
    * Added additional robustness in classes
    * Added additional methods for SQL type info
    * Changed Changelog and README

1.4 (Nov 25 1999) Sinisa Milivojevic <sinisa@mysql.com>

    * Fixed bug in store and storein methods
    * Fixed one serious memory leak
    * Fixed a very serious bug generated by gcc 2.95.xx !!
    * Added robustness in classes, so that e.g. same query and row
    * objects can be re-used
    * Changed sinisa_ex example to reflect and demonstrate this
    * stability
    * Changed Changelog and README
    * Few other bug fixes and small improvements and speed-ups

1.3 (Nov 10 1999) Sinisa Milivojevic <sinisa@mysql.com>

    * Fixed several erronous definitions
    * Further changed source to be 2.95.2 compatible
    * Expunged unused statements, especially dubious ones, like use of
    * pointer_tracker
    * Corrected bug in example file fieldinf1
    * Finally fixed mysql_init in Connection constructor, which provided
    * much greater stability !
    * Added read and get options, so that clients, like mysqlgui can use
    * it
    * Changed Changelog and README
    * Many other bug fixes.

1.2 (Oct 15 1999) Sinisa Milivojevic <sinisa@mysql.com>

    * First offical release. Version 1.0 and 1.1 were releases by Sinisa
    * before I (Kevin Atkinson) made him the offical maintainer,
    * Many manual fixes.
    * Changed README and Changelog
    * Changed source to be compilable by gcc 2.95.xx, tribute to Kevin
    * Atkinson <kevinatk@home.com>
    * Added methods in Connection class which are necessary for
    * fullfilling administrative functions with MySQL
    * Added many bug fixes in code pertaining to missing class
    * initializers , as notified by Michael Rendell <michael@cs.mun.ca>
    * Sinisa Milivojevic <sinisa@mysql.com> is now the offical
    * maintainer.

1.1 (Aug 2 1999) Sinisa Milivojevic <sinisa@mysql.com>

    * Added several bug fixes
    * Fixed memory leak problems and variables overlapping problems.
    * Added automake and autoconf support by loic@ceic.com
    * Added Makefile for manual
    * Added support for cygwin
    * Added example sinisa_ex (let modesty prevail) which used to crash
    * a lot when memory allocation, memory leak and overlap problems
    * were present. Smooth running of this example proves that all those
    * bugs are fixed
    * Corrected bugs in sql_query.cc regarding delete versus delete[]
    * and string length in manip.cc
    * Changed manual
    * Changed README
    * Many other smaller things

1.0 (June 9 1999) Michael Widenius <monty@monty.pp.sci.fi>

    * Added patches from Orion Poplawski <orion@bvt.com> to support the
    * UnixWare 7.0 compiler

.64.1.1a (Sep 27 1998)

    * Fixed several bugs that caused my library to fail to compile with
    * egcs 1.1. Hopefully it will still compile with egcs 1.0 however I
    * have not been able to test it with egcs 1.0.
    * Removed some problem causing debug output in sql++pretty.

.64.1a (Aug 1 1998)

    * Added an (almost) full guide to using Template Queries.
    * Fixed it so the SQLQuery will throw an exception when all the
    * template parameters are not provided.
    * Proofread and speedchecked the manual (it really needed it).
    * Other minor document fixes.

.64.0.1a (July 31 1998)

    * Reworked the Class Reference section a bit.
    * Minor document fixes
    * Added more examples for SSQLS.
    * Changed the syntax of equal_list for SSQLS from equal_list (cchar
    * *, Manip, cchar *) to (cchar *, cchar *, Manip).
    * Added set methods to SSQLS. These new methods do the same thing as
    * there corresponding constructors.
    * Added methods for creating a mysql_type_info from a C++ type_info.

.64.a (July 24 1998)

    * Changed the names of all the classes so they no longer have to
    * have Mysql in the begging of it. However if this creates a problem
    * you can define a macro to only use the old names instead.
    * The Specialized SQL Structures (formally known as Custom Mysql
    * Structures) changed from mysql_ to sql_.
    * Added the option of using exceptions thoughout the API.
    * ColData (formally known as MysqlStrings) will now throw an
    * exception if there is a problem in the conversion.
    * Added a null adapter.
    * Added Mutable Result Sets
    * Added a very basic runtime type identification for SQL types
    * Changed the document format from POD to LYX .
    * Am now using a modified version of Perceps to extract the class
    * information directly from the code to make my life easier.
    * Added an option of defining a macro to avoid using the automatic
    * conversion with binary operators.
    * Other small fixed I probully forgot to mentune.

.63.1.a

    * Added Custom Mysql Structures.
    * Fixed the Copy constructor of class Mysql
    * Started adding code so that class Mysql lets it children now when
    * it is leaving
    * Attempted to compile it into a library but still need help. As
    * default it will compile as a regular program.
    * Other small fixes.

.62.a (May 3 1998)

    * Added Template Queries
    * Created s separate SQLQuery object that is independent of an SQL
    * connection.
    * You no longer have to import the data for the test program as the
    * program creates the database and tables it needs.
    * Many small bug fixes.

.61.1.a (April 28 1998)

    * Cleaned up the example code in test.cc and included it in the
    * manual.
    * Added an interface layout plan to the manual.
    * Added a reverse iterator.
    * Fixed a bug with row.hh (It wasn't being included because of a
    * typo).

.61.0.a

    * Major interface changes. I warned you that the interface may
    * change while it is in pre-alpha state and I wasn't kidding.
    * Created a new and Separate Query Object. You can no longer execute
    * queries from the Mysql object instead you have to create a query
    * object with Mysql::query() and use it to execute queries.
    * Added the comparison operators to MysqlDate, MysqlTime and
    * MysqlDateTime. Fixed a few bugs in the MysqlDate... that effected
    * the stream output and the conversion of them to strings.
    * Reflected the MysqlDate... changes in the manual.
    * Added a new MysqlSet object and a bunch of functions for working
    * with mysql set strings.

.60.3a (April 24 1998)

    * Changed strtoq and strtouq to strtoll and strtull for metter
    * compatibility Minor Manual fix.
    * Changed makefile to make it more compatible with Solaris (Thanks
    * Chris H)
    * Fixed bug in comparison functions so that they would compare in he
    * right direction.
    * Added some items to the to do list be sure to have a look.

Changes to doc/README-manuals-RPM.txt.



1


2




3









































































































































































































































































































4




5


For more information about MySQL++, see its home page:







	http://tangentsoft.net/mysql++/














































































































































































































































































































See the LICENSE file in this directory for the library's license.
>
>
|
>
>

>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

>
>
>
>
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
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
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
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
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
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
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
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
311
312
313
314
Patches for any of these thoughtfully considered!  See the HACKERS file
for instructions on sending patches.

The items in the bug fix/maintenance section are the easiest to do
without breaking things, so if you're looking for a project....

Here's a meta-item that doesn't really fit into any of the categories
below: any time you must hand-roll some SQL code in your program,
consider whether it could be reduced to an API feature that would be
widely useful.  Patches or proposals of this sort are always welcome.


v2.1 Plan
---------

	This plan is not set in stone.	These are simply the features
	we want to try and tackle for the v2.1 release.

	Items in this plan may slip to a future release.  This
	typically happens when the proper solution is unclear,
	so the best way to prevent this is to get on the mailing
	list and help discuss it.  Or even better, provide a patch;
	we rarely reject working code outright.

	Items from the following sections may make it in, but if
	you don't help make that happen, this will just be on the
	whim of one of MySQL++'s developers.  Don't forget that it's
	possible to subclass yourself from the "MySQL++'s developers"
	base class.


	o Transaction support.	Create a "Transaction" class, an
	  object of which you create on the stack, giving it a
	  reference to the Connection object.  Transaction object's
	  ctor calls a function on the Connection object to start
	  a transaction set, and its dtor calls another function to
	  commit the transaction.  Also provide a "commit()" member
	  function, to commit before destruction.  This has a couple
	  of uses.  First, it's useful for avoiding exceptions coming
	  from ~Transaction(), if such a thing is possible.  Second,
	  sometimes it's inconvenient to wait until the end of a block
	  to commit the transaction, and adding artifical blocks is
	  somewhat ugly.

	o Add a configure script option to allow the new lock
	  mechanism to use platform mutexes via the Boost.Threads
	  library.

	  Mechanism must reflect these MySQL C API restrictions:

	  - Only one query executing at once per connection

	  - For "use" queries, Connection (and therefore Query) object must
	    remain locked until last row is consumed

	  - Safest to have one Connection per thread.  Rules for sharing:
	    http://dev.mysql.com/doc/mysql/en/threaded-clients.html

	  Need some way to call mysql_thread_init() and
	  mysql_thread_end() per thread.  Also, work in some way to
	  call mysql_thread_safe() automatically, perhaps the first
	  time through the function that calls mysql_thread_init().
	  If the C API library reports that it is not thread-safe,
	  report this to the caller, perhaps through an exception,
	  or simply by refusing to init more than one thread.

	o Currently, all overloads for Query's execute(), store()
	  and use() methods eventually call the const char*
	  version, which does the actual work of executing the query.
	  This rules out query strings with embedded nulls, as you're
	  likely to get with BLOB columns.  Also, it means MySQL++
	  must scan the string for length in a few places.  The C API
	  isn't limited in this way if you use mysql_real_query(),
	  but you need an accurate length value to call it.  We could
	  get that length with binary data if the end of the call
	  chain were a std::string overload, but we can't do that
	  easily because each of these functions has a version taking
	  a SQLString (a subclass of std:string) for template queries.

	  One way around this is to add a parallel set of functions
	  (e.g. do_execute(), or execute_(), or some such) that take
	  a single std::string, which are the new terminus of the call
	  chain.  Reimplement const char* versions in terms of these.

	  Another way is to rename the template query versions (e.g. to
	  execute_tq()) to avoid the overload conflict.  With that
	  done, we can use C API functions like mysql_real_query(),
	  which can take binary data.

	  Yet another way is to add a length parameter to the call
	  chain end functions.

	  And finally, we may be able to co-opt the first template
	  query version of each of these functions, as it takes a
	  single SQLString.

	o Date and time classes are pretty minimalistic; they could
	  be so much more powerful.  Some ideas:

	  - Add time_t conversion.

	  - Arithmetic features.  (See "Algorithms for Programmers"
	    by Binstock and Rex.)

	  - It may be possible to get some nice syntactic sugar,
	    such as a way to call SQL functions like NOW() when
	    inserting certain Date/Time objects into a Query stream.

	  Don't forget to write an example showing how to use these
	  new mechanisms.

	  It may be possible to find existing date and time classes
	  that can be extended, instead of reinventing the wheel.
	  Boost, perhaps?

	o When you create a Connection object with its default ctor and
	  don't .connect() it, several of its functions can fail to
	  work correctly.  ping(), for one, because the MYSQL handle
	  isn't initialized until the connection is established.
	  Decide how to cope: a) init the handle in all ctors; b)
	  throw ObjectNotInitialized when the library knows the
	  call will fail; or c) just return a failure code and hope
	  the user is checking it.  Could be a different answer for
	  each function.  Keep in mind the consequences for database-
	  independence here.

	o Build a forward iterator mechanism for ResUse.  Make it
	  general enough that you can use it with STL algorithms
	  like find_if().  Then make an example to demonstrate this
	  augmentation of SELECT.  Also, update usequery example
	  to use the iterator.	Tricky bit: how do we make it not
	  interfere with subclass Result's random-access iterator?

	o Write an example to demonstrate compare.h features, or throw
	  the header away.  It's not being used within the library.

	o Have resetdb create a second table containing a BLOB column
	  that load_file and cgi_image can use.  
	  
	  Rework load_image to take the standard command line
	  parameters, and load a JPEG or something into the BLOB table.
	  Include a suitable JPEG with the distribution.  (A cheesy
	  Photoshopped "MySQL++ Rocks!" thing should suffice.)

	  Rework cgi_image so that you can drop it into a cgi-image
	  directory and immediately use it to query the database and
	  return the image data in CGI format.

	o It may be possible to optimize the use of ColData in
	  the return from Row::operator[].  Currently, that operator
	  returns a temporary ColData object, which contains a
	  std::string buffer which is initialized by a const char*
	  pointer to data within the Row object.  Since the ColData
	  object is temporary, you currently must copy the data a
	  second time to store it when using Row::operator[].  If the
	  end user just wants a const char*, this double copy could
	  be prevented.  See http://lists.mysql.com/plusplus/4451
	  for the proposal.


Future Features
---------------

	These changes are planned for versions after v2.1.  If you
	need one of these changes to happen on some particular
	schedule, the best way to ensure it is to start coding and
	provide a patch!


	o Define operator<< for Fields, Row, ResUse, etc.  In other
	  words, there should be a way to get a user-readable version
	  of received data without a lot of code.  Perhaps use a CSV
	  output format, or a mysql(1) one (ASCII grid).

	o Abstract all uses of MySQL C API functions into a database
	  driver class with a generic interface.  This is a step
	  towards database-independence, without the parallel class
	  hierarchy required by the MySQL++ 1.7 design.  Also, it
	  will make it easier to make class Connection completely
	  friend-less.	Right now, the main reason it needs friends
	  is because these other classes make C API calls using its
	  private MYSQL data member.  The other reasons for it having
	  friends aren't nearly as compelling, so it wouldn't be
	  hard to justify redesigning Connection to eliminate these
	  final reasons.

	  While it would be easy to have just one global database
	  driver object, it's probably going to be necessary to have
	  one per Connection.  Consider what happens when you have one
	  program connected to two very different MySQL databases,
	  and you indirectly call C API functions that take MYSQL
	  parameters.  It's likely that those calls are supposed
	  to behave different, depending on the data in that MYSQL
	  object; for instance, different character encodings in the
	  selected databases.  So, there must somehow be a way to pass
	  the database driver's instance pointer down to all objects
	  that will need to use the driver.  A side benefit is that
	  a single program could talk to multiple different database
	  server types.  Imagine a program for importing data from
	  PostgreSQL and loading it into a MySQL table, for instance.

	o manip.cpp uses mysql_escape_string(), which doesn't take the
	  selected database's character set into account.  To do that,
	  you must use mysql_real_escape_string(), which differs
	  by taking a MYSQL instance as an additional parameter.
	  The problem is, Connection owns the relevant MYSQL instance,
	  and the manipulator functionality is implemented in global
	  functions (operator<<() and such) so they have no direct
	  access to the relevant Connection object.

	  The key question for all operator<<'s for manipulators
	  to ask is, "which Query object am I being inserted into?"
	  From there, you can look up the associated Connection object.

	  In some cases, this answer to the question is easy, because
	  the operator takes an ostream parameter, which can be
	  dynamically cast to Query.  From there, it's just a lookup
	  table problem.
	  
	  Other operator<<'s don't take an ostream, but they do take
	  a manipulator.  Right now, manipulators are just enum values,
	  but they could in fact be classes.  Classes can carry data,
	  so there may be a way to "bind" them to the appropriate
	  Connection object.  If not, then perhaps some other method
	  will pop out of the database driver class idea.  The driver
	  object may be able to look up a suitable Connection object
	  for the manipulators.

	o SSQLS structures include some static elements (_table and
	  names[]), which are defined within the macro.  If you
	  put an SSQLS declaration in a header file and #include
	  that from multiple locations, you get a multiply-defined
	  symbol warning.  Some ways to separate the definition from
	  the declaration:

		  o Give the SSQLS macros another parameter, to
		    suppress static definition.

		  o Put statics in a separate macro, which the
		    user must instantiate once in a .cpp file.
		    (Similar to the way MFC message maps work.)

		  o Put statics in a sub-macro, conditionally defined,
		    which SSQLS is implemented in terms of.  Define the
			condition macro in one module within your
			program.

		  o Redesign the SSQLS mechanism entirely.  Instead of
		    defining SSQLSes by instantiating macros, you could
		    declare the structure in, say, an XML format,
		    which could be tranformed (XSLT?  Perl + a DOM
		    parser?) into code very much like in the current
		    SSQLS macros, except that it would generate
		    separate .cpp and .h files for each structure.
		    In addition to solving the static member problem,
		    it would have other advantages, like side-stepping
		    the Borland C++ macro size limit.

	o Deprecate sql_create_basic_* ? They have less functionality
	  and they're no easier to use than sql_create and friends,
	  so why bother with them?  I suppose the code generated
	  is a bit smaller, but *really*....  Only possible saving
	  grace is if BC++ can compile them due to the macro code
	  being shorter.  They also don't have the static members,
	  mentioned in the previous item.

	o Consider whether some of the current boilerplate can be
	  made into a base class that all SSQLSes derive from.
	  This may have implications for some templates, like
	  Query::insert<T>...they might become regular member
	  functions, taking a reference to the base class.

	o MySQL++ handles automatic quoting and escaping differently
	  for cout and cerr than for Query streams.  This should
	  probably be simplified so that automatic quoting is only
	  done for Query streams.  No other stream type should be
	  treated specially.

	o Some field_list() functions use the do_nothing manipulator,
	  while others use the quote manipulator.  Need to pick one.
	  In the vast majority of cases, quoting won't be necessary,
	  so make that the default.  But, it should be possible to turn
	  it on, if needed.  If all uses of quoting are in template
	  code, this can be a #define, allowing different programs
	  built on the same system to get different quoting rules.
	  Otherwise, it will probably have to be a configure script
	  flag, which will "burn" the choice into the built binary.

	o User-settable floating-point comparison precisions?
	  Something like this: http://lists.mysql.com/plusplus/3984
	  As it currently stands, sql_cmp(double,double) is foolish.
	  One shouldn't do exact equality comparison on floating
	  point values.

	o Consider using MySQL C API enum constants in
	  mysql_type_info::types definition instead of hard-coded
	  values.  This could potentially break a lot of
	  infrastructure, though, so do it only with care.


Bug Fix/Maintenance Items
-------------------------

	These items could happen in any version.


	o 64-bit integer support has been reported to work, but more
	  confirmation is wanted.

	o Template ListInsert in lib/myset.h isn't being used within the
	  library.  It could probably be used in place of SetInsert
	  in the same file, which things like type_info.h do use now,
	  but it isn't clear how one would go about doing that without
	  changing the library code.  Document it or throw it away.

Changes to doc/ssqls-pretty.






1
2





3

4




5
6



7
8





9


10
11
12



13
14
15
16
17

18
19






20


21
22



23


24
25
26
27
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
56







57









58


59

60
61









62
63
64
65
66
67

68
69
70




71
72

73



74


75





76
77

78
79




80




81




82
83





#!/usr/bin/perl
use FileHandle;





use IPC::Open2;






if ($ARGV[0] =~ /^--command\=(.+)/) {
    $command = $1;



} else {
    $command = "g++ -E -I /usr/include/mysql";





}



if (-e 'lib/mysql++.h') {
	$command .= " -I lib";



}
else {
	$command .= " -I /usr/include/mysql++/";
}


$/ = undef;
$orgcode = <STDIN>;









($macro) = $orgcode =~ /(sql_create_.+? *\(.+?\))/s;




$out = << "---";



#include <ssqls.h>

$macro

---




$/ = "\n";




$temp_dir = -d '/tmp' ? '/tmp' : $ENV{TMP} || $ENV{TEMP};


#print $out;











open OUT, ">$temp_dir/${$}.cc";

print OUT $out;
close OUT;





system "$command $temp_dir/${$}.cc > $temp_dir/${$}.ii";









open IN, "$temp_dir/${$}.ii";
while (<IN>) {
    next if /^\#/;    
    $code .= $_;

}
close IN;

unlink "$temp_dir/${$}.cc","$temp_dir/${$}.ii";







$_ = $code;



s/\s+/ /g;
s/ *public: */public:\n/g;
s/ *private: */public:\n/g;
s/ *\; */\;\n/g;







s/ *\{ */ \{\n/g;









s/ *\} */ \}\n\n/g;


s/ *\n */\n/g;

s/\{\s+}/\{\}/g;
s/\}\s+\;/\}\;\n/g;










$code = "";
foreach (split /\n/) {
    if (/\}/ && !/\{\}/ ) {
	$indent -= 2;
	$ind = ' 'x$indent;

    }
    $code .= "$ind$_\n" unless /\:$/;
    $code .= "$_\n"     if     /\:$/;




    if (/\{/ && !/\{\}/ ) {
	$indent += 2;

	$ind = ' 'x$indent;



    } 


}






$orgcode =~ s/(sql_create_.+? *\(.+?\))/\n$code\n/s;


print $orgcode;
















>
>
>
>
>
|
|
>
>
>
>
>
|
>

>
>
>
>
|
<
>
>
>
|
|
>
>
>
>
>
|
>
>

|
|
>
>
>
|
|
|
|

>
|
|
>
>
>
>
>
>
|
>
>
|

>
>
>
|
>
>
|
|
|
|

<
>
>
|
>
|
>
|
>
>
|

>
|
|
>
>
>
>
>
>
>
>
>
>
|
>
|
|
>
>
>
>
|
|
>
>
>
>

>
>
>
>
|
<
|
<
>

|

<
>
>
|
>
>
>
>
|
>
>
>
|
|
<
|
>
>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
|
>
>
|
>
|
<
>
>
>
>
>
>
>
>
>

<
<
<
|
<
>
|
<
|
>
>
>
>
|
<
>
|
>
>
>
|
>
>
|
>
>
>
>
>

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

21
22
23
24
25
26
27
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
56
57
58
59
60
61
62
63
64
65
66
67
68
69

70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113

114

115
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
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
191

192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
/***********************************************************************
 multiquery.cpp - Example showing how to iterate over result sets upon
    execution of a query that returns more than one result set.  You can
	get multiple result sets when executing multiple separate SQL
	statments in a single query, or when dealing with the results of
	calling a stored procedure.

 Copyright (c) 1998 by Kevin Atkinson, (c) 1999, 2000 and 2001 by
 MySQL AB, (c) 2004, 2005 by Educational Technology Resources, Inc.,
 and (c) 2005 by Arnon Jalon.  Others may also hold copyrights on
 code in this file.  See the CREDITS file in the top directory of
 the distribution for details.

 This file is part of MySQL++.

 MySQL++ is free software; you can redistribute it and/or modify it
 under the terms of the GNU Lesser General Public License as published
 by the Free Software Foundation; either version 2.1 of the License, or
 (at your option) any later version.


 MySQL++ is distributed in the hope that it will be useful, but WITHOUT
 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
 License for more details.

 You should have received a copy of the GNU Lesser General Public
 License along with MySQL++; if not, write to the Free Software
 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
 USA
***********************************************************************/

#include "cmdline.h"
#include "printdata.h"

#include <mysql++.h>

#include <iostream>
#include <iomanip>
#include <vector>

using namespace std;
using namespace mysqlpp;


typedef vector<int> IntVectorType;


static void
print_header(IntVectorType& widths, StoreQueryResult& res)
{
	cout << "  |" << setfill(' ');
	for (size_t i = 0; i < res.field_names()->size(); i++) {
		cout << " " << setw(widths.at(i)) << res.field_name(i) << " |";
	}
	cout << endl;
}


static void
print_row(IntVectorType& widths, Row& row)
{
	cout << "  |" << setfill(' ');
	for (size_t i = 0; i < row.size(); ++i) {
		cout << " " << setw(widths.at(i)) << row[i] << " |";
	}
	cout << endl;
}



static void
print_row_separator(IntVectorType& widths)
{
	cout << "  +" << setfill('-');
	for (size_t i = 0; i < widths.size(); i++) {
		cout << "-" << setw(widths.at(i)) << '-' << "-+";
	}
	cout << endl;
}


static void
print_result(StoreQueryResult& res, int index)
{
	// Show how many rows are in result, if any
	StoreQueryResult::size_type num_results = res.size();
	if (res && (num_results > 0)) {
		cout << "Result set " << index << " has " << num_results <<
				" row" << (num_results == 1 ? "" : "s") << ':' << endl;
	}
	else {
		cout << "Result set " << index << " is empty." << endl;
		return;
	}

	// Figure out the widths of the result set's columns
	IntVectorType widths;
	int size = res.num_fields();
	for (int i = 0; i < size; i++) {
		widths.push_back(max(
				res.field(i).max_length(),
				res.field_name(i).size()));
	}

	// Print result set header
	print_row_separator(widths);
	print_header(widths, res);
	print_row_separator(widths);

	// Display the result set contents
	for (StoreQueryResult::size_type i = 0; i < num_results; ++i) {
		print_row(widths, res[i]);
	}


	// Print result set footer

	print_row_separator(widths);
}



static void
print_multiple_results(Query& query)
{
	// Execute query and print all result sets
	StoreQueryResult res = query.store();
	print_result(res, 0);
	for (int i = 1; query.more_results(); ++i) {
		res = query.store_next();
		print_result(res, i);
	}
}



int
main(int argc, char *argv[])
{
	// Get connection parameters from command line
    const char* db = 0, *server = 0, *user = 0, *pass = "";
	if (!parse_command_line(argc, argv, &db, &server, &user, &pass)) {
		return 1;
	}

	try {
		// Enable multi-queries.  Notice that you almost always set
		// MySQL++ connection options before establishing the server
		// connection, and options are always set using this one
		// interface.  If you're familiar with the underlying C API,
		// you know that there is poor consistency on these matters;
		// MySQL++ abstracts these differences away.
		Connection con;
		con.set_option(new MultiStatementsOption(true));

		// Connect to the database
		if (!con.connect(db, server, user, pass)) {
			return 1;
		}


		// Set up query with multiple queries.
		Query query = con.query();
		query << "DROP TABLE IF EXISTS test_table; " <<
				"CREATE TABLE test_table(id INT); " <<
				"INSERT INTO test_table VALUES(10); " <<
				"UPDATE test_table SET id=20 WHERE id=10; " <<
				"SELECT * FROM test_table; " <<
				"DROP TABLE test_table";
		cout << "Multi-query: " << endl << query << endl;




		// Execute statement and display all result sets.

		print_multiple_results(query);


#if MYSQL_VERSION_ID >= 50000
		// If it's MySQL v5.0 or higher, also test stored procedures, which
		// return their results the same way multi-queries do.
		query << "DROP PROCEDURE IF EXISTS get_stock; " <<
				"CREATE PROCEDURE get_stock" <<
				"( i_item varchar(20) ) " <<

				"BEGIN " <<
				"SET i_item = concat('%', i_item, '%'); " <<
				"SELECT * FROM stock WHERE lower(item) like lower(i_item); " <<
				"END;";
		cout << "Stored procedure query: " << endl << query << endl;

		// Create the stored procedure.
		print_multiple_results(query);

		// Call the stored procedure and display its results.
		query << "CALL get_stock('relish')";
		cout << "Query: " << query << endl;
		print_multiple_results(query);
#endif


		return 0;
	}

	catch (const BadOption& err) {
		cerr << err.what() << endl;
		cerr << "This example requires MySQL 4.1.1 or later." << endl;
		return 1;
	}
	catch (const ConnectionFailed& err) {
		cerr << "Failed to connect to database server: " <<
				err.what() << endl;
		return 1;
	}
	catch (const Exception& er) {
		// Catch-all for any other MySQL++ exceptions
		cerr << "Error: " << er.what() << endl;
		return 1;
	}
}

Changes to doc/userman/LICENSE.txt.

1
2












3
4




5
6
7




8
9




10

11
12
13
14
15
16



17


18

19




20




21
22
23

24





25
26

27


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



56





57

58

59
MySQL++ User Manual License
~~~~~~~~~~~~~~~~~~~~~~~~~~~













I. COPYRIGHT





    The copyright to the MySQL++ User Manual is owned by its authors.






II. LICENSE






    The MySQL++ User Manual may be reproduced and distributed in whole
    or in part, in any medium physical or electronic, provided that
    this license notice is displayed in the reproduction. Commercial
    redistribution is permitted and encouraged. Thirty days advance
    notice via email to the authors of redistribution is appreciated,
    to give the authors time to provide updated documents.








    A. REQUIREMENTS OF MODIFIED WORKS









        All modified documents, including translations,
        anthologies, and partial documents, must meet the
        following requirements:







            1.  The modified version must be labeled as such.


            2.  The person making the modifications must be


                identified.



            3.  Acknowledgement of the original author must be
                retained.



            4.  The location of the original unmodified
                document be identified.









            5.  The original authors' names may not be used



                to assert or imply endorsement of the
                resulting document without the original

                authors' permission.







        In addition it is requested that:

            1.  The modifications (including deletions)
                be noted.












            2.  The authors be notified by email of the



                modification in advance of redistribution,
                if an email address is provided in
                the document.

        Mere aggregation of the MySQL++ User Manual with other
        documents or programs on the same media shall not cause
        this license to apply to those other works.


        All translations, derivative documents, or modified



        documents that incorporate the MySQL++ User Manual may





        not have more restrictive license terms than these,

        except that you may require distributors to make the

        resulting document available in source format.
|
<
>
>
>
>
>
>
>
>
>
>
>
>

<
>
>
>
>

|

>
>
>
>

<
>
>
>
>

>
|
<
<
<
<
<
>
>
>

>
>

>
|
>
>
>
>

>
>
>
>
|
|
<
>
|
>
>
>
>
>
|
|
>
|
>
>
|
>
>

|
|

>
>
|
|
>
>
>
>
>

>
>
>
|
>
>
>
|
|
>
|
>
>
>
>
>
>

|
|
<
<
>
>
>
>
>
>
>
>
>
|
>
>
|
>
>
>
|
<
<
|
<
<
<
>
|
|
>
>
>
|
>
>
>
>
>
|
>
|
>
|
1

2
3
4
5
6
7
8
9
10
11
12
13
14

15
16
17
18
19
20
21
22
23
24
25
26

27
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
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103


104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120


121



122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
/// \file noexceptions.h

/// \brief Declares interface that allows exceptions to be optional
///
/// A class may inherit from OptionalExceptions, which will add to it
/// a mechanism by which a user can tell objects of that class to
/// suppress exceptions.  (They are enabled by default.)  This module
/// also declares a NoExceptions class, objects of which take a
/// reference to any class derived from OptionalExceptions.  The
/// NoExceptions constructor calls the method that disables exceptions,
/// and the destructor reverts them to the previous state.  One uses
/// the NoExceptions object within a scope to suppress exceptions in
/// that block, without having to worry about reverting the setting when
/// the block exits.


/***********************************************************************
 Copyright (c) 2005 by Educational Technology Resources, Inc.
 Others may also hold copyrights on code in this file.  See the CREDITS
 file in the top directory of the distribution for details.

 This file is part of MySQL++.

 MySQL++ is free software; you can redistribute it and/or modify it
 under the terms of the GNU Lesser General Public License as published
 by the Free Software Foundation; either version 2.1 of the License, or
 (at your option) any later version.


 MySQL++ is distributed in the hope that it will be useful, but WITHOUT
 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
 License for more details.

 You should have received a copy of the GNU Lesser General Public
 License along with MySQL++; if not, write to the Free Software





 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
 USA
***********************************************************************/

#ifndef MYSQLPP_NOEXCEPTIONS_H
#define MYSQLPP_NOEXCEPTIONS_H

namespace mysqlpp {

#if !defined(DOXYGEN_IGNORE)
// Make Doxygen ignore this
class MYSQLPP_EXPORT NoExceptions;
#endif

/// \brief Interface allowing a class to have optional exceptions.
///
/// A class derives from this one to acquire a standard interface for
/// disabling exceptions, possibly only temporarily.  By default,
/// exceptions are enabled.


class MYSQLPP_EXPORT OptionalExceptions
{
public:
	/// \brief Default constructor
	///
	/// \param e if true, exceptions are enabled (this is the default)
	OptionalExceptions(bool e = true) :
	exceptions_(e)
	{
	}

	/// \brief Destroy object
	virtual ~OptionalExceptions() { }

	/// \brief Enable exceptions from the object
	void enable_exceptions() { exceptions_ = true; }

	/// \brief Disable exceptions from the object
	void disable_exceptions() { exceptions_ = false; }

	/// \brief Returns true if exceptions are enabled
	bool throw_exceptions() const { return exceptions_; }

protected:
	/// \brief Sets the exception state to a particular value
	///
	/// This method is protected because it is only intended for use by
	/// subclasses' copy constructors and the like.
	void set_exceptions(bool e) { exceptions_ = e; }

	/// \brief Declare NoExceptions to be our friend so it can access
	/// our protected functions.
	friend class NoExceptions;

private:
	bool exceptions_;
};


/// \brief Disable exceptions in an object derived from
/// OptionalExceptions.
///
/// This class was designed to be created on the stack, taking a
/// reference to a subclass of OptionalExceptions. (We call that our
/// "associate" object.) On creation, we save that object's current
/// exception state, and disable exceptions. On destruction, we restore
/// our associate's previous state.

class MYSQLPP_EXPORT NoExceptions
{


public:
	/// \brief Constructor
	///
	/// Takes a reference to an OptionalExceptions derivative,
	/// saves that object's current exception state, and disables
	/// exceptions.
	NoExceptions(OptionalExceptions& a) :
	assoc_(a),
	exceptions_were_enabled_(a.throw_exceptions())
	{
		assoc_.disable_exceptions();
	}

	/// \brief Destructor
	///
	/// Restores our associate object's previous exception state.
	~NoExceptions()


	{



		assoc_.set_exceptions(exceptions_were_enabled_);
	}
	
private:
	OptionalExceptions& assoc_;
	bool exceptions_were_enabled_;

	// Hidden assignment operator and copy ctor, because we should not
	// be copied.
	NoExceptions(const NoExceptions&);
	NoExceptions& operator=(const NoExceptions&);
};

} // end namespace mysqlpp

#endif // MYSQLPP_NOEXCEPTIONS_H

Changes to doc/userman/Makefile.









1


2




















3






































































































4
5
6
7
8
9


























10
11









12
13
14
15
16
17


18
19
20

21
22
23
24





































































































25

26












27
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


56






























































57


58


59


60


61


62


63


64


65


66





































































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


## Input files




















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







































































































HTML_DIR=../html/userman
BASENAME=userman
DOCFILE=$(BASENAME).dbx
PDFFILE=../pdf/$(BASENAME).pdf
FOFILE=$(BASENAME).fo


























COMMON_SS=common.xsl
FO_SS=fo.xsl









HTML_SS=html.xsl
EX_TXT=cgi_jpeg.txt cpool.txt deadlock.txt fieldinf.txt for_each.txt \
		load_jpeg.txt multiquery.txt resetdb.txt simple1.txt \
		simple2.txt simple3.txt ssqls1.txt ssqls2.txt ssqls3.txt \
		ssqls4.txt ssqls5.txt ssqls6.txt stock.txt store_if.txt \
		tquery1.txt transaction.txt




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

## Major output rules
## ------------------------

html: $(EX_TXT) $(HTML_DIR)/index.html







































































































pdf: $(EX_TXT) $(PDFFILE)















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

## Standard Makefile targets
















































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










# Notice that this is not the first target in the file, as is standard.


# PDF generation takes longer than HTML generation, so to keep the code-


# test-debug-rebuild cycle short, we generate only the HTML manual by


# default.  You can explicitly say "make pdf" or "make all" when you're


# sure the DocBook file's contents are correct.


all: html pdf






































































clean:


	@rm -f tags *.fo $(HTML_DIR)/*.html *.log *.out *.pdf $(EX_TXT) $(PDFFILE)








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


## How to make output files


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










































































$(PDFFILE): *.dbx *.in $(FO_SS) $(COMMON_SS)


	xsltproc --xinclude $(FO_SS) $(DOCFILE) > $(FOFILE)


	mkdir -p ../pdf


	./fo2pdf $(FOFILE) $(PDFFILE)





$(HTML_DIR)/index.html: *.dbx *.in *.mod *.txt *.xsl


	@xmllint --xinclude --nonet --postvalid --noent --noout $(DOCFILE)


	xsltproc --xinclude --nonet -o $(HTML_DIR)/ $(HTML_SS) $(DOCFILE)




































































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


## Dependency rules


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





$(EX_TXT):


	@./mktxt $@





userman.dbx: userman.dbx.in


	( cd ../.. ; ./config.status )





























































>
>
>
>
>
>
>
>
|
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
|
|
|
|
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
<
>
>
>
>
>
>
>
>
>
|
|
<
<
<
<
>
>
|
|
<
>
|
|
|
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

>
|
>
>
>
>
>
>
>
>
>
>
>
>


>
|
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
>
>
>
>
>
>

>
>
|
>
>
|
>
>
|
>
>
|
>
>
|
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

>
>
|
>
>
|
>
>

>
>

>
>
|
>
>
|
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

>
>
|
>
>
|
>
>
|
>
>
|
>
>

>
>
|
>
>
|
>
>
|
>
>

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

>
>
|
>
>
|
>
>
|
>
>

>
>
|
>
>
|
>
>

>
>
|
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
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
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
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
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
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
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
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
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
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
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
# =========================================================================
#     This makefile was generated by
#     Bakefile 0.2.9 (http://www.bakefile.org)
#     Do not modify, all changes will be overwritten!
# =========================================================================



# -------------------------------------------------------------------------
# These are configurable options:
# -------------------------------------------------------------------------

# Compiler flags to link shared library 
LINK_DLL_FLAGS ?= -shared

# C++ compiler 
CXX = g++

# Standard flags for C++ 
CXXFLAGS ?= 

# Standard preprocessor flags (common for CC and CXX) 
CPPFLAGS ?= 

# Standard linker flags 
LDFLAGS ?= 

# Type of compiled binaries [debug,release]
BUILD ?= debug



# -------------------------------------------------------------------------
# Do not modify the rest of this file!
# -------------------------------------------------------------------------

### Variables: ###

CPPDEPS = -MT$@ -MF$@.d -MD -MP
MYSQLPP_CXXFLAGS = $(__DEBUGINFO) $(__OPTIMIZE_FLAG) -mthreads -DUNICODE \
	-D_UNICODE -DMYSQLPP_NO_DLL -DHAVE_MYSQL_SSL_SET -I"C:\Program \
	Files\MySQL\MySQL Connector C 6.1\include" $(CPPFLAGS) $(CXXFLAGS)
MYSQLPP_OBJECTS =  \
	mysqlpp_beemutex.o \
	mysqlpp_cmdline.o \
	mysqlpp_connection.o \
	mysqlpp_cpool.o \
	mysqlpp_datetime.o \
	mysqlpp_dbdriver.o \
	mysqlpp_field_names.o \
	mysqlpp_field_types.o \
	mysqlpp_manip.o \
	mysqlpp_myset.o \
	mysqlpp_mysql++.o \
	mysqlpp_mystring.o \
	mysqlpp_null.o \
	mysqlpp_options.o \
	mysqlpp_qparms.o \
	mysqlpp_query.o \
	mysqlpp_result.o \
	mysqlpp_row.o \
	mysqlpp_scopedconnection.o \
	mysqlpp_sql_buffer.o \
	mysqlpp_sqlstream.o \
	mysqlpp_ssqls2.o \
	mysqlpp_stadapter.o \
	mysqlpp_tcp_connection.o \
	mysqlpp_transaction.o \
	mysqlpp_type_info.o \
	mysqlpp_uds_connection.o \
	mysqlpp_utility.o \
	mysqlpp_vallist.o \
	mysqlpp_wnp_connection.o
SSQLS2PARSE_CXXFLAGS = -mthreads $(__DEBUGINFO) $(__OPTIMIZE_FLAG) -Ilib \
	-I@MYSQL_C_INC_DIR@ -DUNICODE -D_UNICODE -DMYSQLPP_NO_DLL -I"C:\Program \
	Files\MySQL\MySQL Connector C 6.1\include" -I. $(CPPFLAGS) $(CXXFLAGS)
SSQLS2PARSE_OBJECTS =  \
	ssqls2parse_parsev2.o
SSQLSXLAT_CXXFLAGS = -mthreads $(__DEBUGINFO) $(__OPTIMIZE_FLAG) -Ilib \
	-I@MYSQL_C_INC_DIR@ -DUNICODE -D_UNICODE -DMYSQLPP_NO_DLL -I"C:\Program \
	Files\MySQL\MySQL Connector C 6.1\include" $(CPPFLAGS) $(CXXFLAGS)
SSQLSXLAT_OBJECTS =  \
	ssqlsxlat_genv2.o \
	ssqlsxlat_main.o
TEST_ARRAY_INDEX_CXXFLAGS = -mthreads $(__DEBUGINFO) $(__OPTIMIZE_FLAG) -Ilib \
	-I@MYSQL_C_INC_DIR@ -DUNICODE -D_UNICODE -DMYSQLPP_NO_DLL -I"C:\Program \
	Files\MySQL\MySQL Connector C 6.1\include" $(CPPFLAGS) $(CXXFLAGS)
TEST_ARRAY_INDEX_OBJECTS =  \
	test_array_index_array_index.o
TEST_CPOOL_CXXFLAGS = -mthreads $(__DEBUGINFO) $(__OPTIMIZE_FLAG) -Ilib \
	-I@MYSQL_C_INC_DIR@ -DUNICODE -D_UNICODE -DMYSQLPP_NO_DLL -I"C:\Program \
	Files\MySQL\MySQL Connector C 6.1\include" $(CPPFLAGS) $(CXXFLAGS)
TEST_CPOOL_OBJECTS =  \
	test_cpool_cpool.o
TEST_DATETIME_CXXFLAGS = -mthreads $(__DEBUGINFO) $(__OPTIMIZE_FLAG) -Ilib \
	-I@MYSQL_C_INC_DIR@ -DUNICODE -D_UNICODE -DMYSQLPP_NO_DLL -I"C:\Program \
	Files\MySQL\MySQL Connector C 6.1\include" $(CPPFLAGS) $(CXXFLAGS)
TEST_DATETIME_OBJECTS =  \
	test_datetime_datetime.o
TEST_INTTYPES_CXXFLAGS = -mthreads $(__DEBUGINFO) $(__OPTIMIZE_FLAG) -Ilib \
	-I@MYSQL_C_INC_DIR@ -DUNICODE -D_UNICODE -DMYSQLPP_NO_DLL -I"C:\Program \
	Files\MySQL\MySQL Connector C 6.1\include" $(CPPFLAGS) $(CXXFLAGS)
TEST_INTTYPES_OBJECTS =  \
	test_inttypes_inttypes.o
TEST_INSERTPOLICY_CXXFLAGS = -mthreads $(__DEBUGINFO) $(__OPTIMIZE_FLAG) -Ilib \
	-I@MYSQL_C_INC_DIR@ -DUNICODE -D_UNICODE -DMYSQLPP_NO_DLL -I"C:\Program \
	Files\MySQL\MySQL Connector C 6.1\include" $(CPPFLAGS) $(CXXFLAGS)
TEST_INSERTPOLICY_OBJECTS =  \
	test_insertpolicy_insertpolicy.o
TEST_MANIP_CXXFLAGS = -mthreads $(__DEBUGINFO) $(__OPTIMIZE_FLAG) -Ilib \
	-I@MYSQL_C_INC_DIR@ -DUNICODE -D_UNICODE -DMYSQLPP_NO_DLL -I"C:\Program \
	Files\MySQL\MySQL Connector C 6.1\include" $(CPPFLAGS) $(CXXFLAGS)
TEST_MANIP_OBJECTS =  \
	test_manip_manip.o
TEST_NULL_COMPARISON_CXXFLAGS = -mthreads $(__DEBUGINFO) $(__OPTIMIZE_FLAG) \
	-Ilib -I@MYSQL_C_INC_DIR@ -DUNICODE -D_UNICODE -DMYSQLPP_NO_DLL -I"C:\Program \
	Files\MySQL\MySQL Connector C 6.1\include" $(CPPFLAGS) $(CXXFLAGS)
TEST_NULL_COMPARISON_OBJECTS =  \
	test_null_comparison_null_comparison.o
TEST_QUERY_COPY_CXXFLAGS = -mthreads $(__DEBUGINFO) $(__OPTIMIZE_FLAG) -Ilib \
	-I@MYSQL_C_INC_DIR@ -DUNICODE -D_UNICODE -DMYSQLPP_NO_DLL -I"C:\Program \
	Files\MySQL\MySQL Connector C 6.1\include" $(CPPFLAGS) $(CXXFLAGS)
TEST_QUERY_COPY_OBJECTS =  \
	test_query_copy_query_copy.o
TEST_QSSQLS_CXXFLAGS = -mthreads $(__DEBUGINFO) $(__OPTIMIZE_FLAG) -Ilib \
	-I@MYSQL_C_INC_DIR@ -DUNICODE -D_UNICODE -DMYSQLPP_NO_DLL -I"C:\Program \
	Files\MySQL\MySQL Connector C 6.1\include" $(CPPFLAGS) $(CXXFLAGS)
TEST_QSSQLS_OBJECTS =  \
	test_qssqls_qssqls.o
TEST_QSTREAM_CXXFLAGS = -mthreads $(__DEBUGINFO) $(__OPTIMIZE_FLAG) -Ilib \
	-I@MYSQL_C_INC_DIR@ -DUNICODE -D_UNICODE -DMYSQLPP_NO_DLL -I"C:\Program \
	Files\MySQL\MySQL Connector C 6.1\include" $(CPPFLAGS) $(CXXFLAGS)
TEST_QSTREAM_OBJECTS =  \
	test_qstream_qstream.o
TEST_SQLSTREAM_CXXFLAGS = -mthreads $(__DEBUGINFO) $(__OPTIMIZE_FLAG) -Ilib \
	-I@MYSQL_C_INC_DIR@ -DUNICODE -D_UNICODE -DMYSQLPP_NO_DLL -I"C:\Program \
	Files\MySQL\MySQL Connector C 6.1\include" $(CPPFLAGS) $(CXXFLAGS)
TEST_SQLSTREAM_OBJECTS =  \
	test_sqlstream_sqlstream.o
TEST_SSQLS2_CXXFLAGS = -mthreads $(__DEBUGINFO) $(__OPTIMIZE_FLAG) -Ilib \
	-I@MYSQL_C_INC_DIR@ -DUNICODE -D_UNICODE -DMYSQLPP_NO_DLL -I"C:\Program \
	Files\MySQL\MySQL Connector C 6.1\include" $(CPPFLAGS) $(CXXFLAGS)
TEST_SSQLS2_OBJECTS =  \
	test_ssqls2_ssqls2.o
TEST_STRING_CXXFLAGS = -mthreads $(__DEBUGINFO) $(__OPTIMIZE_FLAG) -Ilib \
	-I@MYSQL_C_INC_DIR@ -DUNICODE -D_UNICODE -DMYSQLPP_NO_DLL -I"C:\Program \
	Files\MySQL\MySQL Connector C 6.1\include" $(CPPFLAGS) $(CXXFLAGS)
TEST_STRING_OBJECTS =  \
	test_string_string.o
TEST_TCP_CXXFLAGS = -mthreads $(__DEBUGINFO) $(__OPTIMIZE_FLAG) -Ilib \
	-I@MYSQL_C_INC_DIR@ -DUNICODE -D_UNICODE -DMYSQLPP_NO_DLL -I"C:\Program \
	Files\MySQL\MySQL Connector C 6.1\include" $(CPPFLAGS) $(CXXFLAGS)
TEST_TCP_OBJECTS =  \
	test_tcp_tcp.o
TEST_UDS_CXXFLAGS = -mthreads $(__DEBUGINFO) $(__OPTIMIZE_FLAG) -Ilib \
	-I@MYSQL_C_INC_DIR@ -DUNICODE -D_UNICODE -DMYSQLPP_NO_DLL -I"C:\Program \
	Files\MySQL\MySQL Connector C 6.1\include" $(CPPFLAGS) $(CXXFLAGS)
TEST_UDS_OBJECTS =  \
	test_uds_uds.o
TEST_WNP_CXXFLAGS = -mthreads $(__DEBUGINFO) $(__OPTIMIZE_FLAG) -Ilib \
	-I@MYSQL_C_INC_DIR@ -DUNICODE -D_UNICODE -DMYSQLPP_NO_DLL -I"C:\Program \
	Files\MySQL\MySQL Connector C 6.1\include" $(CPPFLAGS) $(CXXFLAGS)
TEST_WNP_OBJECTS =  \
	test_wnp_wnp.o
EXCOMMON_CXXFLAGS = -mthreads $(__DEBUGINFO) $(__OPTIMIZE_FLAG) -Ilib \
	-I@MYSQL_C_INC_DIR@ -DUNICODE -D_UNICODE -DMYSQLPP_NO_DLL -I"C:\Program \
	Files\MySQL\MySQL Connector C 6.1\include" $(CPPFLAGS) $(CXXFLAGS)
EXCOMMON_OBJECTS =  \

	excommon_printdata.o
CGI_JPEG_CXXFLAGS = -mthreads $(__DEBUGINFO) $(__OPTIMIZE_FLAG) -Ilib \
	-I@MYSQL_C_INC_DIR@ -DUNICODE -D_UNICODE -DMYSQLPP_NO_DLL -I"C:\Program \
	Files\MySQL\MySQL Connector C 6.1\include" $(CPPFLAGS) $(CXXFLAGS)
CGI_JPEG_OBJECTS =  \
	cgi_jpeg_cgi_jpeg.o
CPOOL_CXXFLAGS = -mthreads $(__DEBUGINFO) $(__OPTIMIZE_FLAG) -Ilib \
	-I@MYSQL_C_INC_DIR@ -DUNICODE -D_UNICODE -DMYSQLPP_NO_DLL -I"C:\Program \
	Files\MySQL\MySQL Connector C 6.1\include" $(CPPFLAGS) $(CXXFLAGS)
CPOOL_OBJECTS =  \
	cpool_cpool.o




DBINFO_CXXFLAGS = -mthreads $(__DEBUGINFO) $(__OPTIMIZE_FLAG) -Ilib \
	-I@MYSQL_C_INC_DIR@ -DUNICODE -D_UNICODE -DMYSQLPP_NO_DLL -I"C:\Program \
	Files\MySQL\MySQL Connector C 6.1\include" $(CPPFLAGS) $(CXXFLAGS)
DBINFO_OBJECTS =  \

	dbinfo_dbinfo.o
DEADLOCK_CXXFLAGS = -mthreads $(__DEBUGINFO) $(__OPTIMIZE_FLAG) -Ilib \
	-I@MYSQL_C_INC_DIR@ -DUNICODE -D_UNICODE -DMYSQLPP_NO_DLL -I"C:\Program \
	Files\MySQL\MySQL Connector C 6.1\include" $(CPPFLAGS) $(CXXFLAGS)
DEADLOCK_OBJECTS =  \
	deadlock_deadlock.o
FIELDINF_CXXFLAGS = -mthreads $(__DEBUGINFO) $(__OPTIMIZE_FLAG) -Ilib \
	-I@MYSQL_C_INC_DIR@ -DUNICODE -D_UNICODE -DMYSQLPP_NO_DLL -I"C:\Program \
	Files\MySQL\MySQL Connector C 6.1\include" $(CPPFLAGS) $(CXXFLAGS)
FIELDINF_OBJECTS =  \
	fieldinf_fieldinf.o
FOR_EACH_CXXFLAGS = -mthreads $(__DEBUGINFO) $(__OPTIMIZE_FLAG) -Ilib \
	-I@MYSQL_C_INC_DIR@ -DUNICODE -D_UNICODE -DMYSQLPP_NO_DLL -I"C:\Program \
	Files\MySQL\MySQL Connector C 6.1\include" $(CPPFLAGS) $(CXXFLAGS)
FOR_EACH_OBJECTS =  \
	for_each_for_each.o
LOAD_JPEG_CXXFLAGS = -mthreads $(__DEBUGINFO) $(__OPTIMIZE_FLAG) -Ilib \
	-I@MYSQL_C_INC_DIR@ -DUNICODE -D_UNICODE -DMYSQLPP_NO_DLL -I"C:\Program \
	Files\MySQL\MySQL Connector C 6.1\include" $(CPPFLAGS) $(CXXFLAGS)
LOAD_JPEG_OBJECTS =  \
	load_jpeg_load_jpeg.o
MULTIQUERY_CXXFLAGS = -mthreads $(__DEBUGINFO) $(__OPTIMIZE_FLAG) -Ilib \
	-I@MYSQL_C_INC_DIR@ -DUNICODE -D_UNICODE -DMYSQLPP_NO_DLL -I"C:\Program \
	Files\MySQL\MySQL Connector C 6.1\include" $(CPPFLAGS) $(CXXFLAGS)
MULTIQUERY_OBJECTS =  \
	multiquery_multiquery.o
RESETDB_CXXFLAGS = -mthreads $(__DEBUGINFO) $(__OPTIMIZE_FLAG) -Ilib \
	-I@MYSQL_C_INC_DIR@ -DUNICODE -D_UNICODE -DMYSQLPP_NO_DLL -I"C:\Program \
	Files\MySQL\MySQL Connector C 6.1\include" $(CPPFLAGS) $(CXXFLAGS)
RESETDB_OBJECTS =  \
	resetdb_resetdb.o
SIMPLE1_CXXFLAGS = -mthreads $(__DEBUGINFO) $(__OPTIMIZE_FLAG) -Ilib \
	-I@MYSQL_C_INC_DIR@ -DUNICODE -D_UNICODE -DMYSQLPP_NO_DLL -I"C:\Program \
	Files\MySQL\MySQL Connector C 6.1\include" $(CPPFLAGS) $(CXXFLAGS)
SIMPLE1_OBJECTS =  \
	simple1_simple1.o
SIMPLE2_CXXFLAGS = -mthreads $(__DEBUGINFO) $(__OPTIMIZE_FLAG) -Ilib \
	-I@MYSQL_C_INC_DIR@ -DUNICODE -D_UNICODE -DMYSQLPP_NO_DLL -I"C:\Program \
	Files\MySQL\MySQL Connector C 6.1\include" $(CPPFLAGS) $(CXXFLAGS)
SIMPLE2_OBJECTS =  \
	simple2_simple2.o
SIMPLE3_CXXFLAGS = -mthreads $(__DEBUGINFO) $(__OPTIMIZE_FLAG) -Ilib \
	-I@MYSQL_C_INC_DIR@ -DUNICODE -D_UNICODE -DMYSQLPP_NO_DLL -I"C:\Program \
	Files\MySQL\MySQL Connector C 6.1\include" $(CPPFLAGS) $(CXXFLAGS)
SIMPLE3_OBJECTS =  \
	simple3_simple3.o
SSQLS1_CXXFLAGS = -mthreads $(__DEBUGINFO) $(__OPTIMIZE_FLAG) -Ilib \
	-I@MYSQL_C_INC_DIR@ -DUNICODE -D_UNICODE -DMYSQLPP_NO_DLL -I"C:\Program \
	Files\MySQL\MySQL Connector C 6.1\include" $(CPPFLAGS) $(CXXFLAGS)
SSQLS1_OBJECTS =  \
	ssqls1_ssqls1.o
SSQLS2_CXXFLAGS = -mthreads $(__DEBUGINFO) $(__OPTIMIZE_FLAG) -Ilib \
	-I@MYSQL_C_INC_DIR@ -DUNICODE -D_UNICODE -DMYSQLPP_NO_DLL -I"C:\Program \
	Files\MySQL\MySQL Connector C 6.1\include" $(CPPFLAGS) $(CXXFLAGS)
SSQLS2_OBJECTS =  \
	ssqls2_ssqls2.o
SSQLS3_CXXFLAGS = -mthreads $(__DEBUGINFO) $(__OPTIMIZE_FLAG) -Ilib \
	-I@MYSQL_C_INC_DIR@ -DUNICODE -D_UNICODE -DMYSQLPP_NO_DLL -I"C:\Program \
	Files\MySQL\MySQL Connector C 6.1\include" $(CPPFLAGS) $(CXXFLAGS)
SSQLS3_OBJECTS =  \
	ssqls3_ssqls3.o
SSQLS4_CXXFLAGS = -mthreads $(__DEBUGINFO) $(__OPTIMIZE_FLAG) -Ilib \
	-I@MYSQL_C_INC_DIR@ -DUNICODE -D_UNICODE -DMYSQLPP_NO_DLL -I"C:\Program \
	Files\MySQL\MySQL Connector C 6.1\include" $(CPPFLAGS) $(CXXFLAGS)
SSQLS4_OBJECTS =  \
	ssqls4_ssqls4.o
SSQLS5_CXXFLAGS = -mthreads $(__DEBUGINFO) $(__OPTIMIZE_FLAG) -Ilib \
	-I@MYSQL_C_INC_DIR@ -DUNICODE -D_UNICODE -DMYSQLPP_NO_DLL -I"C:\Program \
	Files\MySQL\MySQL Connector C 6.1\include" $(CPPFLAGS) $(CXXFLAGS)
SSQLS5_OBJECTS =  \
	ssqls5_ssqls5.o
SSQLS6_CXXFLAGS = -mthreads $(__DEBUGINFO) $(__OPTIMIZE_FLAG) -Ilib \
	-I@MYSQL_C_INC_DIR@ -DUNICODE -D_UNICODE -DMYSQLPP_NO_DLL -I"C:\Program \
	Files\MySQL\MySQL Connector C 6.1\include" $(CPPFLAGS) $(CXXFLAGS)
SSQLS6_OBJECTS =  \
	ssqls6_ssqls6.o
STORE_IF_CXXFLAGS = -mthreads $(__DEBUGINFO) $(__OPTIMIZE_FLAG) -Ilib \
	-I@MYSQL_C_INC_DIR@ -DUNICODE -D_UNICODE -DMYSQLPP_NO_DLL -I"C:\Program \
	Files\MySQL\MySQL Connector C 6.1\include" $(CPPFLAGS) $(CXXFLAGS)
STORE_IF_OBJECTS =  \
	store_if_store_if.o
TQUERY1_CXXFLAGS = -mthreads $(__DEBUGINFO) $(__OPTIMIZE_FLAG) -Ilib \
	-I@MYSQL_C_INC_DIR@ -DUNICODE -D_UNICODE -DMYSQLPP_NO_DLL -I"C:\Program \
	Files\MySQL\MySQL Connector C 6.1\include" $(CPPFLAGS) $(CXXFLAGS)
TQUERY1_OBJECTS =  \
	tquery1_tquery1.o
TQUERY2_CXXFLAGS = -mthreads $(__DEBUGINFO) $(__OPTIMIZE_FLAG) -Ilib \
	-I@MYSQL_C_INC_DIR@ -DUNICODE -D_UNICODE -DMYSQLPP_NO_DLL -I"C:\Program \
	Files\MySQL\MySQL Connector C 6.1\include" $(CPPFLAGS) $(CXXFLAGS)
TQUERY2_OBJECTS =  \
	tquery2_tquery2.o
TQUERY3_CXXFLAGS = -mthreads $(__DEBUGINFO) $(__OPTIMIZE_FLAG) -Ilib \
	-I@MYSQL_C_INC_DIR@ -DUNICODE -D_UNICODE -DMYSQLPP_NO_DLL -I"C:\Program \
	Files\MySQL\MySQL Connector C 6.1\include" $(CPPFLAGS) $(CXXFLAGS)
TQUERY3_OBJECTS =  \
	tquery3_tquery3.o
TQUERY4_CXXFLAGS = -mthreads $(__DEBUGINFO) $(__OPTIMIZE_FLAG) -Ilib \
	-I@MYSQL_C_INC_DIR@ -DUNICODE -D_UNICODE -DMYSQLPP_NO_DLL -I"C:\Program \
	Files\MySQL\MySQL Connector C 6.1\include" $(CPPFLAGS) $(CXXFLAGS)
TQUERY4_OBJECTS =  \
	tquery4_tquery4.o
TRANSACTION_CXXFLAGS = -mthreads $(__DEBUGINFO) $(__OPTIMIZE_FLAG) -Ilib \
	-I@MYSQL_C_INC_DIR@ -DUNICODE -D_UNICODE -DMYSQLPP_NO_DLL -I"C:\Program \
	Files\MySQL\MySQL Connector C 6.1\include" $(CPPFLAGS) $(CXXFLAGS)
TRANSACTION_OBJECTS =  \
	transaction_transaction.o

### Conditionally set variables: ###

ifeq ($(BUILD),debug)
__OPTIMIZE_FLAG = -O0
endif
ifeq ($(BUILD),release)
__OPTIMIZE_FLAG = -O2
endif
ifeq ($(BUILD),debug)
__DEBUGINFO = -g
endif
ifeq ($(BUILD),release)
__DEBUGINFO = 
endif


### Targets: ###

all: mysqlpp.dll libmysqlpp_ssqls2parse.a ssqlsxlat.exe test_array_index.exe test_cpool.exe test_datetime.exe test_inttypes.exe test_insertpolicy.exe test_manip.exe test_null_comparison.exe test_query_copy.exe test_qssqls.exe test_qstream.exe test_sqlstream.exe test_ssqls2.exe test_string.exe test_tcp.exe test_uds.exe test_wnp.exe libmysqlpp_excommon.a cgi_jpeg.exe cpool.exe dbinfo.exe deadlock.exe fieldinf.exe for_each.exe load_jpeg.exe multiquery.exe resetdb.exe simple1.exe simple2.exe simple3.exe ssqls1.exe ssqls2.exe ssqls3.exe ssqls4.exe ssqls5.exe ssqls6.exe store_if.exe tquery1.exe tquery2.exe tquery3.exe tquery4.exe transaction.exe

clean: 
	-if exist .\*.o del .\*.o
	-if exist .\*.d del .\*.d
	-if exist mysqlpp.dll del mysqlpp.dll
	-if exist libmysqlpp.a del libmysqlpp.a
	-if exist libmysqlpp_ssqls2parse.a del libmysqlpp_ssqls2parse.a
	-if exist ssqlsxlat.exe del ssqlsxlat.exe
	-if exist test_array_index.exe del test_array_index.exe
	-if exist test_cpool.exe del test_cpool.exe
	-if exist test_datetime.exe del test_datetime.exe
	-if exist test_inttypes.exe del test_inttypes.exe
	-if exist test_insertpolicy.exe del test_insertpolicy.exe
	-if exist test_manip.exe del test_manip.exe
	-if exist test_null_comparison.exe del test_null_comparison.exe
	-if exist test_query_copy.exe del test_query_copy.exe
	-if exist test_qssqls.exe del test_qssqls.exe
	-if exist test_qstream.exe del test_qstream.exe
	-if exist test_sqlstream.exe del test_sqlstream.exe
	-if exist test_ssqls2.exe del test_ssqls2.exe
	-if exist test_string.exe del test_string.exe
	-if exist test_tcp.exe del test_tcp.exe
	-if exist test_uds.exe del test_uds.exe
	-if exist test_wnp.exe del test_wnp.exe
	-if exist libmysqlpp_excommon.a del libmysqlpp_excommon.a
	-if exist cgi_jpeg.exe del cgi_jpeg.exe
	-if exist cpool.exe del cpool.exe
	-if exist dbinfo.exe del dbinfo.exe
	-if exist deadlock.exe del deadlock.exe
	-if exist fieldinf.exe del fieldinf.exe
	-if exist for_each.exe del for_each.exe
	-if exist load_jpeg.exe del load_jpeg.exe
	-if exist multiquery.exe del multiquery.exe
	-if exist resetdb.exe del resetdb.exe
	-if exist simple1.exe del simple1.exe
	-if exist simple2.exe del simple2.exe
	-if exist simple3.exe del simple3.exe
	-if exist ssqls1.exe del ssqls1.exe
	-if exist ssqls2.exe del ssqls2.exe
	-if exist ssqls3.exe del ssqls3.exe
	-if exist ssqls4.exe del ssqls4.exe
	-if exist ssqls5.exe del ssqls5.exe
	-if exist ssqls6.exe del ssqls6.exe
	-if exist store_if.exe del store_if.exe
	-if exist tquery1.exe del tquery1.exe
	-if exist tquery2.exe del tquery2.exe
	-if exist tquery3.exe del tquery3.exe
	-if exist tquery4.exe del tquery4.exe
	-if exist transaction.exe del transaction.exe

mysqlpp.dll: $(MYSQLPP_OBJECTS)
	$(CXX) $(LINK_DLL_FLAGS) -fPIC -o $@ $(MYSQLPP_OBJECTS)  -Wl,--out-implib=libmysqlpp.a $(__DEBUGINFO) -mthreads -Wl,--enable-stdcall-fixup -L"C:\Program Files\MySQL\MySQL Connector C 6.1\lib" $(LDFLAGS)  -lwsock32 -lmysql

libmysqlpp_ssqls2parse.a: $(SSQLS2PARSE_OBJECTS) mysqlpp.dll mysqlpp.dll
	if exist $@ del $@
	ar rcu $@ $(SSQLS2PARSE_OBJECTS)
	ranlib $@

ssqlsxlat.exe: $(SSQLSXLAT_OBJECTS) mysqlpp.dll libmysqlpp_ssqls2parse.a
	$(CXX) -o $@ $(SSQLSXLAT_OBJECTS)  -mthreads $(__DEBUGINFO) -L@MYSQL_C_LIB_DIR@ -L. -Wl,--enable-auto-import -Wl,--enable-runtime-pseudo-reloc -Wl,--enable-stdcall-fixup -L"C:\Program Files\MySQL\MySQL Connector C 6.1\lib" $(LDFLAGS)  -lmysql -lmysqlpp -lmysqlpp_ssqls2parse -lmysqlpp

test_array_index.exe: $(TEST_ARRAY_INDEX_OBJECTS) mysqlpp.dll
	$(CXX) -o $@ $(TEST_ARRAY_INDEX_OBJECTS)  -mthreads $(__DEBUGINFO) -L@MYSQL_C_LIB_DIR@ -L. -Wl,--enable-auto-import -Wl,--enable-runtime-pseudo-reloc -Wl,--enable-stdcall-fixup -L"C:\Program Files\MySQL\MySQL Connector C 6.1\lib" $(LDFLAGS)  -lmysql -lmysqlpp

test_cpool.exe: $(TEST_CPOOL_OBJECTS) mysqlpp.dll
	$(CXX) -o $@ $(TEST_CPOOL_OBJECTS)  -mthreads $(__DEBUGINFO) -L@MYSQL_C_LIB_DIR@ -L. -Wl,--enable-auto-import -Wl,--enable-runtime-pseudo-reloc -Wl,--enable-stdcall-fixup -L"C:\Program Files\MySQL\MySQL Connector C 6.1\lib" $(LDFLAGS)  -lmysql -lmysqlpp

test_datetime.exe: $(TEST_DATETIME_OBJECTS) mysqlpp.dll
	$(CXX) -o $@ $(TEST_DATETIME_OBJECTS)  -mthreads $(__DEBUGINFO) -L@MYSQL_C_LIB_DIR@ -L. -Wl,--enable-auto-import -Wl,--enable-runtime-pseudo-reloc -Wl,--enable-stdcall-fixup -L"C:\Program Files\MySQL\MySQL Connector C 6.1\lib" $(LDFLAGS)  -lmysql -lmysqlpp

test_inttypes.exe: $(TEST_INTTYPES_OBJECTS) mysqlpp.dll
	$(CXX) -o $@ $(TEST_INTTYPES_OBJECTS)  -mthreads $(__DEBUGINFO) -L@MYSQL_C_LIB_DIR@ -L. -Wl,--enable-auto-import -Wl,--enable-runtime-pseudo-reloc -Wl,--enable-stdcall-fixup -L"C:\Program Files\MySQL\MySQL Connector C 6.1\lib" $(LDFLAGS)  -lmysql -lmysqlpp

test_insertpolicy.exe: $(TEST_INSERTPOLICY_OBJECTS) mysqlpp.dll
	$(CXX) -o $@ $(TEST_INSERTPOLICY_OBJECTS)  -mthreads $(__DEBUGINFO) -L@MYSQL_C_LIB_DIR@ -L. -Wl,--enable-auto-import -Wl,--enable-runtime-pseudo-reloc -Wl,--enable-stdcall-fixup -L"C:\Program Files\MySQL\MySQL Connector C 6.1\lib" $(LDFLAGS)  -lmysql -lmysqlpp

test_manip.exe: $(TEST_MANIP_OBJECTS) mysqlpp.dll
	$(CXX) -o $@ $(TEST_MANIP_OBJECTS)  -mthreads $(__DEBUGINFO) -L@MYSQL_C_LIB_DIR@ -L. -Wl,--enable-auto-import -Wl,--enable-runtime-pseudo-reloc -Wl,--enable-stdcall-fixup -L"C:\Program Files\MySQL\MySQL Connector C 6.1\lib" $(LDFLAGS)  -lmysql -lmysqlpp

test_null_comparison.exe: $(TEST_NULL_COMPARISON_OBJECTS) mysqlpp.dll
	$(CXX) -o $@ $(TEST_NULL_COMPARISON_OBJECTS)  -mthreads $(__DEBUGINFO) -L@MYSQL_C_LIB_DIR@ -L. -Wl,--enable-auto-import -Wl,--enable-runtime-pseudo-reloc -Wl,--enable-stdcall-fixup -L"C:\Program Files\MySQL\MySQL Connector C 6.1\lib" $(LDFLAGS)  -lmysql -lmysqlpp

test_query_copy.exe: $(TEST_QUERY_COPY_OBJECTS) mysqlpp.dll
	$(CXX) -o $@ $(TEST_QUERY_COPY_OBJECTS)  -mthreads $(__DEBUGINFO) -L@MYSQL_C_LIB_DIR@ -L. -Wl,--enable-auto-import -Wl,--enable-runtime-pseudo-reloc -Wl,--enable-stdcall-fixup -L"C:\Program Files\MySQL\MySQL Connector C 6.1\lib" $(LDFLAGS)  -lmysql -lmysqlpp

test_qssqls.exe: $(TEST_QSSQLS_OBJECTS) mysqlpp.dll
	$(CXX) -o $@ $(TEST_QSSQLS_OBJECTS)  -mthreads $(__DEBUGINFO) -L@MYSQL_C_LIB_DIR@ -L. -Wl,--enable-auto-import -Wl,--enable-runtime-pseudo-reloc -Wl,--enable-stdcall-fixup -L"C:\Program Files\MySQL\MySQL Connector C 6.1\lib" $(LDFLAGS)  -lmysql -lmysqlpp

test_qstream.exe: $(TEST_QSTREAM_OBJECTS) mysqlpp.dll
	$(CXX) -o $@ $(TEST_QSTREAM_OBJECTS)  -mthreads $(__DEBUGINFO) -L@MYSQL_C_LIB_DIR@ -L. -Wl,--enable-auto-import -Wl,--enable-runtime-pseudo-reloc -Wl,--enable-stdcall-fixup -L"C:\Program Files\MySQL\MySQL Connector C 6.1\lib" $(LDFLAGS)  -lmysql -lmysqlpp

test_sqlstream.exe: $(TEST_SQLSTREAM_OBJECTS) mysqlpp.dll
	$(CXX) -o $@ $(TEST_SQLSTREAM_OBJECTS)  -mthreads $(__DEBUGINFO) -L@MYSQL_C_LIB_DIR@ -L. -Wl,--enable-auto-import -Wl,--enable-runtime-pseudo-reloc -Wl,--enable-stdcall-fixup -L"C:\Program Files\MySQL\MySQL Connector C 6.1\lib" $(LDFLAGS)  -lmysql -lmysqlpp

test_ssqls2.exe: $(TEST_SSQLS2_OBJECTS) mysqlpp.dll libmysqlpp_ssqls2parse.a
	$(CXX) -o $@ $(TEST_SSQLS2_OBJECTS)  -mthreads $(__DEBUGINFO) -L@MYSQL_C_LIB_DIR@ -L. -Wl,--enable-auto-import -Wl,--enable-runtime-pseudo-reloc -Wl,--enable-stdcall-fixup -L"C:\Program Files\MySQL\MySQL Connector C 6.1\lib" $(LDFLAGS)  -lmysql -lmysqlpp -lmysqlpp_ssqls2parse -lmysqlpp

test_string.exe: $(TEST_STRING_OBJECTS) mysqlpp.dll
	$(CXX) -o $@ $(TEST_STRING_OBJECTS)  -mthreads $(__DEBUGINFO) -L@MYSQL_C_LIB_DIR@ -L. -Wl,--enable-auto-import -Wl,--enable-runtime-pseudo-reloc -Wl,--enable-stdcall-fixup -L"C:\Program Files\MySQL\MySQL Connector C 6.1\lib" $(LDFLAGS)  -lmysql -lmysqlpp

test_tcp.exe: $(TEST_TCP_OBJECTS) mysqlpp.dll
	$(CXX) -o $@ $(TEST_TCP_OBJECTS)  -mthreads $(__DEBUGINFO) -L@MYSQL_C_LIB_DIR@ -L. -Wl,--enable-auto-import -Wl,--enable-runtime-pseudo-reloc -Wl,--enable-stdcall-fixup -L"C:\Program Files\MySQL\MySQL Connector C 6.1\lib" $(LDFLAGS)  -lmysql -lmysqlpp

test_uds.exe: $(TEST_UDS_OBJECTS) mysqlpp.dll
	$(CXX) -o $@ $(TEST_UDS_OBJECTS)  -mthreads $(__DEBUGINFO) -L@MYSQL_C_LIB_DIR@ -L. -Wl,--enable-auto-import -Wl,--enable-runtime-pseudo-reloc -Wl,--enable-stdcall-fixup -L"C:\Program Files\MySQL\MySQL Connector C 6.1\lib" $(LDFLAGS)  -lmysql -lmysqlpp

test_wnp.exe: $(TEST_WNP_OBJECTS) mysqlpp.dll
	$(CXX) -o $@ $(TEST_WNP_OBJECTS)  -mthreads $(__DEBUGINFO) -L@MYSQL_C_LIB_DIR@ -L. -Wl,--enable-auto-import -Wl,--enable-runtime-pseudo-reloc -Wl,--enable-stdcall-fixup -L"C:\Program Files\MySQL\MySQL Connector C 6.1\lib" $(LDFLAGS)  -lmysql -lmysqlpp

libmysqlpp_excommon.a: $(EXCOMMON_OBJECTS) mysqlpp.dll
	if exist $@ del $@
	ar rcu $@ $(EXCOMMON_OBJECTS)
	ranlib $@

cgi_jpeg.exe: $(CGI_JPEG_OBJECTS) libmysqlpp_excommon.a mysqlpp.dll
	$(CXX) -o $@ $(CGI_JPEG_OBJECTS)  -mthreads $(__DEBUGINFO) -L@MYSQL_C_LIB_DIR@ -L. -Wl,--enable-auto-import -Wl,--enable-runtime-pseudo-reloc -Wl,--enable-stdcall-fixup -L"C:\Program Files\MySQL\MySQL Connector C 6.1\lib" $(LDFLAGS)  -lmysqlpp_excommon -lmysql -lmysqlpp

cpool.exe: $(CPOOL_OBJECTS) libmysqlpp_excommon.a mysqlpp.dll
	$(CXX) -o $@ $(CPOOL_OBJECTS)  -mthreads $(__DEBUGINFO) -L@MYSQL_C_LIB_DIR@ -L. -Wl,--enable-auto-import -Wl,--enable-runtime-pseudo-reloc -Wl,--enable-stdcall-fixup -L"C:\Program Files\MySQL\MySQL Connector C 6.1\lib" $(LDFLAGS)  -lmysqlpp_excommon -lmysql -lmysqlpp

dbinfo.exe: $(DBINFO_OBJECTS) libmysqlpp_excommon.a mysqlpp.dll
	$(CXX) -o $@ $(DBINFO_OBJECTS)  -mthreads $(__DEBUGINFO) -L@MYSQL_C_LIB_DIR@ -L. -Wl,--enable-auto-import -Wl,--enable-runtime-pseudo-reloc -Wl,--enable-stdcall-fixup -L"C:\Program Files\MySQL\MySQL Connector C 6.1\lib" $(LDFLAGS)  -lmysqlpp_excommon -lmysql -lmysqlpp

deadlock.exe: $(DEADLOCK_OBJECTS) libmysqlpp_excommon.a mysqlpp.dll
	$(CXX) -o $@ $(DEADLOCK_OBJECTS)  -mthreads $(__DEBUGINFO) -L@MYSQL_C_LIB_DIR@ -L. -Wl,--enable-auto-import -Wl,--enable-runtime-pseudo-reloc -Wl,--enable-stdcall-fixup -L"C:\Program Files\MySQL\MySQL Connector C 6.1\lib" $(LDFLAGS)  -lmysqlpp_excommon -lmysql -lmysqlpp

fieldinf.exe: $(FIELDINF_OBJECTS) libmysqlpp_excommon.a mysqlpp.dll
	$(CXX) -o $@ $(FIELDINF_OBJECTS)  -mthreads $(__DEBUGINFO) -L@MYSQL_C_LIB_DIR@ -L. -Wl,--enable-auto-import -Wl,--enable-runtime-pseudo-reloc -Wl,--enable-stdcall-fixup -L"C:\Program Files\MySQL\MySQL Connector C 6.1\lib" $(LDFLAGS)  -lmysqlpp_excommon -lmysql -lmysqlpp

for_each.exe: $(FOR_EACH_OBJECTS) libmysqlpp_excommon.a mysqlpp.dll
	$(CXX) -o $@ $(FOR_EACH_OBJECTS)  -mthreads $(__DEBUGINFO) -L@MYSQL_C_LIB_DIR@ -L. -Wl,--enable-auto-import -Wl,--enable-runtime-pseudo-reloc -Wl,--enable-stdcall-fixup -L"C:\Program Files\MySQL\MySQL Connector C 6.1\lib" $(LDFLAGS)  -lmysqlpp_excommon -lmysql -lmysqlpp

load_jpeg.exe: $(LOAD_JPEG_OBJECTS) libmysqlpp_excommon.a mysqlpp.dll
	$(CXX) -o $@ $(LOAD_JPEG_OBJECTS)  -mthreads $(__DEBUGINFO) -L@MYSQL_C_LIB_DIR@ -L. -Wl,--enable-auto-import -Wl,--enable-runtime-pseudo-reloc -Wl,--enable-stdcall-fixup -L"C:\Program Files\MySQL\MySQL Connector C 6.1\lib" $(LDFLAGS)  -lmysqlpp_excommon -lmysql -lmysqlpp

multiquery.exe: $(MULTIQUERY_OBJECTS) libmysqlpp_excommon.a mysqlpp.dll
	$(CXX) -o $@ $(MULTIQUERY_OBJECTS)  -mthreads $(__DEBUGINFO) -L@MYSQL_C_LIB_DIR@ -L. -Wl,--enable-auto-import -Wl,--enable-runtime-pseudo-reloc -Wl,--enable-stdcall-fixup -L"C:\Program Files\MySQL\MySQL Connector C 6.1\lib" $(LDFLAGS)  -lmysqlpp_excommon -lmysql -lmysqlpp

resetdb.exe: $(RESETDB_OBJECTS) libmysqlpp_excommon.a mysqlpp.dll
	$(CXX) -o $@ $(RESETDB_OBJECTS)  -mthreads $(__DEBUGINFO) -L@MYSQL_C_LIB_DIR@ -L. -Wl,--enable-auto-import -Wl,--enable-runtime-pseudo-reloc -Wl,--enable-stdcall-fixup -L"C:\Program Files\MySQL\MySQL Connector C 6.1\lib" $(LDFLAGS)  -lmysqlpp_excommon -lmysql -lmysqlpp

simple1.exe: $(SIMPLE1_OBJECTS) libmysqlpp_excommon.a mysqlpp.dll
	$(CXX) -o $@ $(SIMPLE1_OBJECTS)  -mthreads $(__DEBUGINFO) -L@MYSQL_C_LIB_DIR@ -L. -Wl,--enable-auto-import -Wl,--enable-runtime-pseudo-reloc -Wl,--enable-stdcall-fixup -L"C:\Program Files\MySQL\MySQL Connector C 6.1\lib" $(LDFLAGS)  -lmysqlpp_excommon -lmysql -lmysqlpp

simple2.exe: $(SIMPLE2_OBJECTS) libmysqlpp_excommon.a mysqlpp.dll
	$(CXX) -o $@ $(SIMPLE2_OBJECTS)  -mthreads $(__DEBUGINFO) -L@MYSQL_C_LIB_DIR@ -L. -Wl,--enable-auto-import -Wl,--enable-runtime-pseudo-reloc -Wl,--enable-stdcall-fixup -L"C:\Program Files\MySQL\MySQL Connector C 6.1\lib" $(LDFLAGS)  -lmysqlpp_excommon -lmysql -lmysqlpp

simple3.exe: $(SIMPLE3_OBJECTS) libmysqlpp_excommon.a mysqlpp.dll
	$(CXX) -o $@ $(SIMPLE3_OBJECTS)  -mthreads $(__DEBUGINFO) -L@MYSQL_C_LIB_DIR@ -L. -Wl,--enable-auto-import -Wl,--enable-runtime-pseudo-reloc -Wl,--enable-stdcall-fixup -L"C:\Program Files\MySQL\MySQL Connector C 6.1\lib" $(LDFLAGS)  -lmysqlpp_excommon -lmysql -lmysqlpp

ssqls1.exe: $(SSQLS1_OBJECTS) libmysqlpp_excommon.a mysqlpp.dll
	$(CXX) -o $@ $(SSQLS1_OBJECTS)  -mthreads $(__DEBUGINFO) -L@MYSQL_C_LIB_DIR@ -L. -Wl,--enable-auto-import -Wl,--enable-runtime-pseudo-reloc -Wl,--enable-stdcall-fixup -L"C:\Program Files\MySQL\MySQL Connector C 6.1\lib" $(LDFLAGS)  -lmysqlpp_excommon -lmysql -lmysqlpp

ssqls2.exe: $(SSQLS2_OBJECTS) libmysqlpp_excommon.a mysqlpp.dll
	$(CXX) -o $@ $(SSQLS2_OBJECTS)  -mthreads $(__DEBUGINFO) -L@MYSQL_C_LIB_DIR@ -L. -Wl,--enable-auto-import -Wl,--enable-runtime-pseudo-reloc -Wl,--enable-stdcall-fixup -L"C:\Program Files\MySQL\MySQL Connector C 6.1\lib" $(LDFLAGS)  -lmysqlpp_excommon -lmysql -lmysqlpp

ssqls3.exe: $(SSQLS3_OBJECTS) libmysqlpp_excommon.a mysqlpp.dll
	$(CXX) -o $@ $(SSQLS3_OBJECTS)  -mthreads $(__DEBUGINFO) -L@MYSQL_C_LIB_DIR@ -L. -Wl,--enable-auto-import -Wl,--enable-runtime-pseudo-reloc -Wl,--enable-stdcall-fixup -L"C:\Program Files\MySQL\MySQL Connector C 6.1\lib" $(LDFLAGS)  -lmysqlpp_excommon -lmysql -lmysqlpp

ssqls4.exe: $(SSQLS4_OBJECTS) libmysqlpp_excommon.a mysqlpp.dll
	$(CXX) -o $@ $(SSQLS4_OBJECTS)  -mthreads $(__DEBUGINFO) -L@MYSQL_C_LIB_DIR@ -L. -Wl,--enable-auto-import -Wl,--enable-runtime-pseudo-reloc -Wl,--enable-stdcall-fixup -L"C:\Program Files\MySQL\MySQL Connector C 6.1\lib" $(LDFLAGS)  -lmysqlpp_excommon -lmysql -lmysqlpp

ssqls5.exe: $(SSQLS5_OBJECTS) libmysqlpp_excommon.a mysqlpp.dll
	$(CXX) -o $@ $(SSQLS5_OBJECTS)  -mthreads $(__DEBUGINFO) -L@MYSQL_C_LIB_DIR@ -L. -Wl,--enable-auto-import -Wl,--enable-runtime-pseudo-reloc -Wl,--enable-stdcall-fixup -L"C:\Program Files\MySQL\MySQL Connector C 6.1\lib" $(LDFLAGS)  -lmysqlpp_excommon -lmysql -lmysqlpp

ssqls6.exe: $(SSQLS6_OBJECTS) libmysqlpp_excommon.a mysqlpp.dll
	$(CXX) -o $@ $(SSQLS6_OBJECTS)  -mthreads $(__DEBUGINFO) -L@MYSQL_C_LIB_DIR@ -L. -Wl,--enable-auto-import -Wl,--enable-runtime-pseudo-reloc -Wl,--enable-stdcall-fixup -L"C:\Program Files\MySQL\MySQL Connector C 6.1\lib" $(LDFLAGS)  -lmysqlpp_excommon -lmysql -lmysqlpp

store_if.exe: $(STORE_IF_OBJECTS) libmysqlpp_excommon.a mysqlpp.dll
	$(CXX) -o $@ $(STORE_IF_OBJECTS)  -mthreads $(__DEBUGINFO) -L@MYSQL_C_LIB_DIR@ -L. -Wl,--enable-auto-import -Wl,--enable-runtime-pseudo-reloc -Wl,--enable-stdcall-fixup -L"C:\Program Files\MySQL\MySQL Connector C 6.1\lib" $(LDFLAGS)  -lmysqlpp_excommon -lmysql -lmysqlpp

tquery1.exe: $(TQUERY1_OBJECTS) libmysqlpp_excommon.a mysqlpp.dll
	$(CXX) -o $@ $(TQUERY1_OBJECTS)  -mthreads $(__DEBUGINFO) -L@MYSQL_C_LIB_DIR@ -L. -Wl,--enable-auto-import -Wl,--enable-runtime-pseudo-reloc -Wl,--enable-stdcall-fixup -L"C:\Program Files\MySQL\MySQL Connector C 6.1\lib" $(LDFLAGS)  -lmysqlpp_excommon -lmysql -lmysqlpp

tquery2.exe: $(TQUERY2_OBJECTS) libmysqlpp_excommon.a mysqlpp.dll
	$(CXX) -o $@ $(TQUERY2_OBJECTS)  -mthreads $(__DEBUGINFO) -L@MYSQL_C_LIB_DIR@ -L. -Wl,--enable-auto-import -Wl,--enable-runtime-pseudo-reloc -Wl,--enable-stdcall-fixup -L"C:\Program Files\MySQL\MySQL Connector C 6.1\lib" $(LDFLAGS)  -lmysqlpp_excommon -lmysql -lmysqlpp

tquery3.exe: $(TQUERY3_OBJECTS) libmysqlpp_excommon.a mysqlpp.dll
	$(CXX) -o $@ $(TQUERY3_OBJECTS)  -mthreads $(__DEBUGINFO) -L@MYSQL_C_LIB_DIR@ -L. -Wl,--enable-auto-import -Wl,--enable-runtime-pseudo-reloc -Wl,--enable-stdcall-fixup -L"C:\Program Files\MySQL\MySQL Connector C 6.1\lib" $(LDFLAGS)  -lmysqlpp_excommon -lmysql -lmysqlpp

tquery4.exe: $(TQUERY4_OBJECTS) libmysqlpp_excommon.a mysqlpp.dll
	$(CXX) -o $@ $(TQUERY4_OBJECTS)  -mthreads $(__DEBUGINFO) -L@MYSQL_C_LIB_DIR@ -L. -Wl,--enable-auto-import -Wl,--enable-runtime-pseudo-reloc -Wl,--enable-stdcall-fixup -L"C:\Program Files\MySQL\MySQL Connector C 6.1\lib" $(LDFLAGS)  -lmysqlpp_excommon -lmysql -lmysqlpp

transaction.exe: $(TRANSACTION_OBJECTS) libmysqlpp_excommon.a mysqlpp.dll
	$(CXX) -o $@ $(TRANSACTION_OBJECTS)  -mthreads $(__DEBUGINFO) -L@MYSQL_C_LIB_DIR@ -L. -Wl,--enable-auto-import -Wl,--enable-runtime-pseudo-reloc -Wl,--enable-stdcall-fixup -L"C:\Program Files\MySQL\MySQL Connector C 6.1\lib" $(LDFLAGS)  -lmysqlpp_excommon -lmysql -lmysqlpp

mysqlpp_beemutex.o: ./lib/beemutex.cpp
	$(CXX) -c -o $@ $(MYSQLPP_CXXFLAGS) $(CPPDEPS) $<

mysqlpp_cmdline.o: ./lib/cmdline.cpp
	$(CXX) -c -o $@ $(MYSQLPP_CXXFLAGS) $(CPPDEPS) $<

mysqlpp_connection.o: ./lib/connection.cpp
	$(CXX) -c -o $@ $(MYSQLPP_CXXFLAGS) $(CPPDEPS) $<

mysqlpp_cpool.o: ./lib/cpool.cpp
	$(CXX) -c -o $@ $(MYSQLPP_CXXFLAGS) $(CPPDEPS) $<

mysqlpp_datetime.o: ./lib/datetime.cpp
	$(CXX) -c -o $@ $(MYSQLPP_CXXFLAGS) $(CPPDEPS) $<

mysqlpp_dbdriver.o: ./lib/dbdriver.cpp
	$(CXX) -c -o $@ $(MYSQLPP_CXXFLAGS) $(CPPDEPS) $<

mysqlpp_field_names.o: ./lib/field_names.cpp
	$(CXX) -c -o $@ $(MYSQLPP_CXXFLAGS) $(CPPDEPS) $<

mysqlpp_field_types.o: ./lib/field_types.cpp
	$(CXX) -c -o $@ $(MYSQLPP_CXXFLAGS) $(CPPDEPS) $<

mysqlpp_manip.o: ./lib/manip.cpp
	$(CXX) -c -o $@ $(MYSQLPP_CXXFLAGS) $(CPPDEPS) $<

mysqlpp_myset.o: ./lib/myset.cpp
	$(CXX) -c -o $@ $(MYSQLPP_CXXFLAGS) $(CPPDEPS) $<

mysqlpp_mysql++.o: ./lib/mysql++.cpp
	$(CXX) -c -o $@ $(MYSQLPP_CXXFLAGS) $(CPPDEPS) $<

mysqlpp_mystring.o: ./lib/mystring.cpp
	$(CXX) -c -o $@ $(MYSQLPP_CXXFLAGS) $(CPPDEPS) $<

mysqlpp_null.o: ./lib/null.cpp
	$(CXX) -c -o $@ $(MYSQLPP_CXXFLAGS) $(CPPDEPS) $<

mysqlpp_options.o: ./lib/options.cpp
	$(CXX) -c -o $@ $(MYSQLPP_CXXFLAGS) $(CPPDEPS) $<

mysqlpp_qparms.o: ./lib/qparms.cpp
	$(CXX) -c -o $@ $(MYSQLPP_CXXFLAGS) $(CPPDEPS) $<

mysqlpp_query.o: ./lib/query.cpp
	$(CXX) -c -o $@ $(MYSQLPP_CXXFLAGS) $(CPPDEPS) $<

mysqlpp_result.o: ./lib/result.cpp
	$(CXX) -c -o $@ $(MYSQLPP_CXXFLAGS) $(CPPDEPS) $<

mysqlpp_row.o: ./lib/row.cpp
	$(CXX) -c -o $@ $(MYSQLPP_CXXFLAGS) $(CPPDEPS) $<

mysqlpp_scopedconnection.o: ./lib/scopedconnection.cpp
	$(CXX) -c -o $@ $(MYSQLPP_CXXFLAGS) $(CPPDEPS) $<

mysqlpp_sql_buffer.o: ./lib/sql_buffer.cpp
	$(CXX) -c -o $@ $(MYSQLPP_CXXFLAGS) $(CPPDEPS) $<

mysqlpp_sqlstream.o: ./lib/sqlstream.cpp
	$(CXX) -c -o $@ $(MYSQLPP_CXXFLAGS) $(CPPDEPS) $<

mysqlpp_ssqls2.o: ./lib/ssqls2.cpp
	$(CXX) -c -o $@ $(MYSQLPP_CXXFLAGS) $(CPPDEPS) $<

mysqlpp_stadapter.o: ./lib/stadapter.cpp
	$(CXX) -c -o $@ $(MYSQLPP_CXXFLAGS) $(CPPDEPS) $<

mysqlpp_tcp_connection.o: ./lib/tcp_connection.cpp
	$(CXX) -c -o $@ $(MYSQLPP_CXXFLAGS) $(CPPDEPS) $<

mysqlpp_transaction.o: ./lib/transaction.cpp
	$(CXX) -c -o $@ $(MYSQLPP_CXXFLAGS) $(CPPDEPS) $<

mysqlpp_type_info.o: ./lib/type_info.cpp
	$(CXX) -c -o $@ $(MYSQLPP_CXXFLAGS) $(CPPDEPS) $<

mysqlpp_uds_connection.o: ./lib/uds_connection.cpp
	$(CXX) -c -o $@ $(MYSQLPP_CXXFLAGS) $(CPPDEPS) $<

mysqlpp_utility.o: ./lib/utility.cpp
	$(CXX) -c -o $@ $(MYSQLPP_CXXFLAGS) $(CPPDEPS) $<

mysqlpp_vallist.o: ./lib/vallist.cpp
	$(CXX) -c -o $@ $(MYSQLPP_CXXFLAGS) $(CPPDEPS) $<

mysqlpp_wnp_connection.o: ./lib/wnp_connection.cpp
	$(CXX) -c -o $@ $(MYSQLPP_CXXFLAGS) $(CPPDEPS) $<

ssqls2parse_parsev2.o: ./ssx/parsev2.cpp
	$(CXX) -c -o $@ $(SSQLS2PARSE_CXXFLAGS) $(CPPDEPS) $<

ssqlsxlat_genv2.o: ./ssx/genv2.cpp
	$(CXX) -c -o $@ $(SSQLSXLAT_CXXFLAGS) $(CPPDEPS) $<

ssqlsxlat_main.o: ./ssx/main.cpp
	$(CXX) -c -o $@ $(SSQLSXLAT_CXXFLAGS) $(CPPDEPS) $<

test_array_index_array_index.o: ./test/array_index.cpp
	$(CXX) -c -o $@ $(TEST_ARRAY_INDEX_CXXFLAGS) $(CPPDEPS) $<

test_cpool_cpool.o: ./test/cpool.cpp
	$(CXX) -c -o $@ $(TEST_CPOOL_CXXFLAGS) $(CPPDEPS) $<

test_datetime_datetime.o: ./test/datetime.cpp
	$(CXX) -c -o $@ $(TEST_DATETIME_CXXFLAGS) $(CPPDEPS) $<

test_inttypes_inttypes.o: ./test/inttypes.cpp
	$(CXX) -c -o $@ $(TEST_INTTYPES_CXXFLAGS) $(CPPDEPS) $<

test_insertpolicy_insertpolicy.o: ./test/insertpolicy.cpp
	$(CXX) -c -o $@ $(TEST_INSERTPOLICY_CXXFLAGS) $(CPPDEPS) $<

test_manip_manip.o: ./test/manip.cpp
	$(CXX) -c -o $@ $(TEST_MANIP_CXXFLAGS) $(CPPDEPS) $<

test_null_comparison_null_comparison.o: ./test/null_comparison.cpp
	$(CXX) -c -o $@ $(TEST_NULL_COMPARISON_CXXFLAGS) $(CPPDEPS) $<

test_query_copy_query_copy.o: ./test/query_copy.cpp
	$(CXX) -c -o $@ $(TEST_QUERY_COPY_CXXFLAGS) $(CPPDEPS) $<

test_qssqls_qssqls.o: ./test/qssqls.cpp
	$(CXX) -c -o $@ $(TEST_QSSQLS_CXXFLAGS) $(CPPDEPS) $<

test_qstream_qstream.o: ./test/qstream.cpp
	$(CXX) -c -o $@ $(TEST_QSTREAM_CXXFLAGS) $(CPPDEPS) $<

test_sqlstream_sqlstream.o: ./test/sqlstream.cpp
	$(CXX) -c -o $@ $(TEST_SQLSTREAM_CXXFLAGS) $(CPPDEPS) $<

test_ssqls2_ssqls2.o: ./test/ssqls2.cpp
	$(CXX) -c -o $@ $(TEST_SSQLS2_CXXFLAGS) $(CPPDEPS) $<

test_string_string.o: ./test/string.cpp
	$(CXX) -c -o $@ $(TEST_STRING_CXXFLAGS) $(CPPDEPS) $<

test_tcp_tcp.o: ./test/tcp.cpp
	$(CXX) -c -o $@ $(TEST_TCP_CXXFLAGS) $(CPPDEPS) $<

test_uds_uds.o: ./test/uds.cpp
	$(CXX) -c -o $@ $(TEST_UDS_CXXFLAGS) $(CPPDEPS) $<

test_wnp_wnp.o: ./test/wnp.cpp
	$(CXX) -c -o $@ $(TEST_WNP_CXXFLAGS) $(CPPDEPS) $<

excommon_printdata.o: ./examples/printdata.cpp
	$(CXX) -c -o $@ $(EXCOMMON_CXXFLAGS) $(CPPDEPS) $<

cgi_jpeg_cgi_jpeg.o: ./examples/cgi_jpeg.cpp
	$(CXX) -c -o $@ $(CGI_JPEG_CXXFLAGS) $(CPPDEPS) $<

cpool_cpool.o: ./examples/cpool.cpp
	$(CXX) -c -o $@ $(CPOOL_CXXFLAGS) $(CPPDEPS) $<

dbinfo_dbinfo.o: ./examples/dbinfo.cpp
	$(CXX) -c -o $@ $(DBINFO_CXXFLAGS) $(CPPDEPS) $<

deadlock_deadlock.o: ./examples/deadlock.cpp
	$(CXX) -c -o $@ $(DEADLOCK_CXXFLAGS) $(CPPDEPS) $<

fieldinf_fieldinf.o: ./examples/fieldinf.cpp
	$(CXX) -c -o $@ $(FIELDINF_CXXFLAGS) $(CPPDEPS) $<

for_each_for_each.o: ./examples/for_each.cpp
	$(CXX) -c -o $@ $(FOR_EACH_CXXFLAGS) $(CPPDEPS) $<

load_jpeg_load_jpeg.o: ./examples/load_jpeg.cpp
	$(CXX) -c -o $@ $(LOAD_JPEG_CXXFLAGS) $(CPPDEPS) $<

multiquery_multiquery.o: ./examples/multiquery.cpp
	$(CXX) -c -o $@ $(MULTIQUERY_CXXFLAGS) $(CPPDEPS) $<

resetdb_resetdb.o: ./examples/resetdb.cpp
	$(CXX) -c -o $@ $(RESETDB_CXXFLAGS) $(CPPDEPS) $<

simple1_simple1.o: ./examples/simple1.cpp
	$(CXX) -c -o $@ $(SIMPLE1_CXXFLAGS) $(CPPDEPS) $<

simple2_simple2.o: ./examples/simple2.cpp
	$(CXX) -c -o $@ $(SIMPLE2_CXXFLAGS) $(CPPDEPS) $<

simple3_simple3.o: ./examples/simple3.cpp
	$(CXX) -c -o $@ $(SIMPLE3_CXXFLAGS) $(CPPDEPS) $<

ssqls1_ssqls1.o: ./examples/ssqls1.cpp
	$(CXX) -c -o $@ $(SSQLS1_CXXFLAGS) $(CPPDEPS) $<

ssqls2_ssqls2.o: ./examples/ssqls2.cpp
	$(CXX) -c -o $@ $(SSQLS2_CXXFLAGS) $(CPPDEPS) $<

ssqls3_ssqls3.o: ./examples/ssqls3.cpp
	$(CXX) -c -o $@ $(SSQLS3_CXXFLAGS) $(CPPDEPS) $<

ssqls4_ssqls4.o: ./examples/ssqls4.cpp
	$(CXX) -c -o $@ $(SSQLS4_CXXFLAGS) $(CPPDEPS) $<

ssqls5_ssqls5.o: ./examples/ssqls5.cpp
	$(CXX) -c -o $@ $(SSQLS5_CXXFLAGS) $(CPPDEPS) $<

ssqls6_ssqls6.o: ./examples/ssqls6.cpp
	$(CXX) -c -o $@ $(SSQLS6_CXXFLAGS) $(CPPDEPS) $<

store_if_store_if.o: ./examples/store_if.cpp
	$(CXX) -c -o $@ $(STORE_IF_CXXFLAGS) $(CPPDEPS) $<

tquery1_tquery1.o: ./examples/tquery1.cpp
	$(CXX) -c -o $@ $(TQUERY1_CXXFLAGS) $(CPPDEPS) $<

tquery2_tquery2.o: ./examples/tquery2.cpp
	$(CXX) -c -o $@ $(TQUERY2_CXXFLAGS) $(CPPDEPS) $<

tquery3_tquery3.o: ./examples/tquery3.cpp
	$(CXX) -c -o $@ $(TQUERY3_CXXFLAGS) $(CPPDEPS) $<

tquery4_tquery4.o: ./examples/tquery4.cpp
	$(CXX) -c -o $@ $(TQUERY4_CXXFLAGS) $(CPPDEPS) $<

transaction_transaction.o: ./examples/transaction.cpp
	$(CXX) -c -o $@ $(TRANSACTION_CXXFLAGS) $(CPPDEPS) $<

.PHONY: all clean


SHELL := $(COMSPEC)

# Dependencies tracking:
-include ./*.d

Changes to doc/userman/Makefile.hello.mingw.

1








2





3




4




5





6






7


8
9











10
11
SHELL := $(COMSPEC)








MYSQL_DIR := "c:/Program Files/MySQL/MySQL Connector C 6.1"





CXXFLAGS := -I$(MYSQL_DIR)/include -Ic:/MySQL++/include




LDFLAGS := -L$(MYSQL_DIR)/lib -Lc:/MySQL++/lib/MinGW




LDLIBS := -lmysql -lmysqlpp





EXECUTABLE := hello









all: $(EXECUTABLE)












clean: 
	del $(EXECUTABLE)
|
>
>
>
>
>
>
>
>
|
>
>
>
>
>
|
>
>
>
>
|
>
>
>
>
|
>
>
>
>
>
|
>
>
>
>
>
>

>
>
|

>
>
>
>
>
>
>
>
>
>
>
|
<
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
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

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE article PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"
                         "http://www.docbook.org/xml/4.2/docbookx.dtd"
[ <!ENTITY % xinclude SYSTEM "xinclude.mod">
%xinclude;
]>
<article>
	<articleinfo>
		<title>MySQL++ v3.2.2 User Manual</title>

		<authorgroup>
			<author>
				<firstname>Kevin</firstname>
				<surname>Atkinson</surname>
			</author>

			<author>
				<firstname>Sinisa</firstname>
				<surname>Milivojevic</surname>
			</author>

			<author>
				<firstname>Monty</firstname>
				<surname>Widenius</surname>
			</author>

			<author>
				<firstname>Warren</firstname>
				<surname>Young</surname>
			</author>
		</authorgroup>

		<copyright>
			<year>1998-2001, 2005-2015</year>
			<holder>Kevin Atkinson (original author)</holder>
			<holder>MySQL AB</holder>
			<holder>Educational Technology Resources</holder>
		</copyright>

		<pubdate><?dbtimestamp format="B d, Y"?></pubdate>
	</articleinfo>


	<xi:include href="intro.dbx" xmlns:xi="http://www.w3.org/2001/XInclude"/>
	<xi:include href="overview.dbx" xmlns:xi="http://www.w3.org/2001/XInclude"/>
	<xi:include href="tutorial.dbx" xmlns:xi="http://www.w3.org/2001/XInclude"/>
	<xi:include href="tquery.dbx" xmlns:xi="http://www.w3.org/2001/XInclude"/>
	<xi:include href="ssqls.dbx" xmlns:xi="http://www.w3.org/2001/XInclude"/>
	<xi:include href="unicode.dbx" xmlns:xi="http://www.w3.org/2001/XInclude"/>
	<xi:include href="threads.dbx" xmlns:xi="http://www.w3.org/2001/XInclude"/>
	<xi:include href="configuration.dbx" xmlns:xi="http://www.w3.org/2001/XInclude"/>
	<xi:include href="incorporating.dbx" xmlns:xi="http://www.w3.org/2001/XInclude"/>
	<xi:include href="breakages.dbx" xmlns:xi="http://www.w3.org/2001/XInclude"/>
	<xi:include href="licenses.dbx" xmlns:xi="http://www.w3.org/2001/XInclude"/>
</article>

Changes to doc/userman/Makefile.hello.posix.






1






2

3




4













































































5











6











7


8



9






































































CXXFLAGS := -I/usr/include/mysql -I/usr/local/include/mysql++






LDFLAGS := -L/usr/local/lib

LDLIBS := -lmysqlpp -lmysqlclient




EXECUTABLE := hello

























































































all: $(EXECUTABLE)














clean: 



    rm -f $(EXECUTABLE) *.o

































































>
>
>
>
>
|
>
>
>
>
>
>
|
>
|
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

>
>
>
>
>
>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>

>
>
|
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
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
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
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
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
191
192
193
194
/// \file common.h
/// \brief This file includes top-level definitions for use both
/// internal to the library, and outside it.  Contrast mysql++.h
///
/// This file mostly takes care of platform differences.

/***********************************************************************
 Copyright (c) 1998 by Kevin Atkinson, (c) 1999-2001 by MySQL AB,
 (c) 2004-2009 by Educational Technology Resources, Inc., and
 (c) 2009 by Warren Young.  Others may also hold copyrights on code
 in this file.  See the CREDITS.txt file in the top directory of the
 distribution for details.

 This file is part of MySQL++.

 MySQL++ is free software; you can redistribute it and/or modify it
 under the terms of the GNU Lesser General Public License as published
 by the Free Software Foundation; either version 2.1 of the License, or
 (at your option) any later version.

 MySQL++ is distributed in the hope that it will be useful, but WITHOUT
 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
 License for more details.

 You should have received a copy of the GNU Lesser General Public
 License along with MySQL++; if not, write to the Free Software
 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
 USA
***********************************************************************/

#if !defined(MYSQLPP_COMMON_H)
#define MYSQLPP_COMMON_H

#if !defined(DOXYGEN_IGNORE)
// Doxygen will not generate documentation for the following stuff.

// Enable SSQLS by default.  Turned off below on platforms where we
// know it doesn't work.
#define MYSQLPP_SSQLS_COMPATIBLE

// For all platforms but Visual C++ 2003, the following macro is just
// an alias for "*this".  It needs a more complicated definition on
// VC++ 2003 to work around an error in the overloaded operator lookup
// logic.  For an explanation of the problem, see:
// http://groups.google.com/group/microsoft.public.vc.stl/browse_thread/thread/9a68d84644e64f15
#define MYSQLPP_QUERY_THISPTR *this

// Work out major platform-specific stuff here.
#if defined(__WIN32__) || defined(_WIN32)
#	define MYSQLPP_PLATFORM_WINDOWS
	// Windows compiler support.  Tested with Microsoft Visual C++,
	// Borland C++ Builder, and MinGW GCC.

	// Don't let windows.h (via Connector/C) #define min/max
	#define NOMINMAX

	// Stuff for Visual C++ only
#	if defined(_MSC_VER)
#		define MYSQLPP_PLATFORM_VISUAL_CPP
		// MS *still* doesn't ship stdint.h, through VC++ 2008 at least.
		// This means we have to take a wild guess at appropriate
		// integer types in lib/sql_types.h.  See test/inttypes.cpp for
		// tests that check whether we've guessed well.
#		define MYSQLPP_NO_STDINT_H
#		if _MSC_VER < 1400
			// Workarounds for limitations of VC++ 2003 that are fixed
			// in 2005 and later.
#			undef MYSQLPP_QUERY_THISPTR
#			define MYSQLPP_QUERY_THISPTR dynamic_cast<std::ostream&>(*this)
#			undef MYSQLPP_SSQLS_COMPATIBLE
#		elif !defined(_STLP_VERSION) && !defined(_STLP_VERSION_STR)
			// VC++ 2005 or newer and not using STLport, so #define
			// portability flags indicating features we can use from
			// the compiler's native RTL.
#			define MYSQLPP_HAVE_LOCALTIME_S
#			define MYSQLPP_HAVE_STD__NOINIT
#		endif

		// Disable complaints about STL data members: VC++ believes
		// these need to be __declspec(dllexport) for some reason.
#		pragma warning(disable: 4251)
		// Disable complaint that VC++ doesn't grok throw specs
#		pragma warning(disable: 4290)
		// Disable whining about using 'this' as a member initializer on VC++.
#		pragma warning(disable: 4355)
		// Disable whining about implicit conversions to bool
#		pragma warning(disable: 4800)
		// Disable nagging about new "secure" functions like strncpy_s()
#		pragma warning(disable: 4996)
		// Call _snprintf() for VC++ version of snprintf() function
#		define snprintf _snprintf
#	endif

	// Define DLL import/export tags for Windows compilers, where we build
	// the library into a DLL, for LGPL license compatibility reasons.
	// (This is based on a similar mechanism in wxWindows.)

	#ifdef MYSQLPP_MAKING_DLL
		// When making the DLL, export tagged symbols, so they appear
		// in the import library.
		#define MYSQLPP_EXPORT __declspec(dllexport)
	#elif !defined(MYSQLPP_NO_DLL)
		// We must be _using_ the DLL, so import symbols instead.
		#define MYSQLPP_EXPORT __declspec(dllimport)
	#else
		// Not making a DLL at all, so no-op these declspecs
		#define MYSQLPP_EXPORT
	#endif

	// We need to use the DOS/Windows path separator here
	#define MYSQLPP_PATH_SEPARATOR '\\'
#else
	// If not VC++, MinGW, or Xcode, we assume we're on a system using
	// autoconf, so bring in the config.h file it wrote containing the
	// config test results.  Only do this during the library build, and
	// even then, not if included from a MySQL++ header file, since
	// config.h cannot be safely installed with the other headers.
#	if defined(MYSQLPP_NOT_HEADER) && !defined(MYSQLPP_XCODE)
#		include "config.h"
#	endif

	// Make DLL stuff a no-op on this platform.
	#define MYSQLPP_EXPORT

	// Assume POSIX path separator
	#define MYSQLPP_PATH_SEPARATOR '/'
#endif

#if defined(MYSQLPP_MYSQL_HEADERS_BURIED)
#	include <mysql/mysql_version.h>
#else
#	include <mysql_version.h>
#endif

namespace mysqlpp {

/// \brief Alias for 'true', to make code requesting exceptions more
/// readable.
const bool use_exceptions = true;

/// \brief Used to disambiguate overloads of equal_list() in SSQLSes.
enum sql_cmp_type { sql_use_compare };

#if !defined(DOXYGEN_IGNORE)
// Figure out how to get large integer support on this system.  Suppress
// refman documentation for these typedefs, as they're system-dependent.
#if defined(MYSQLPP_NO_LONG_LONGS)
// Alias "longlong" and "ulonglong" to the regular "long" counterparts
typedef unsigned long ulonglong;
typedef long longlong;
#elif defined(_MSC_VER)
// It's VC++, so we'll use Microsoft's 64-bit integer types
typedef unsigned __int64 ulonglong;
typedef __int64 longlong;
#else
// No better idea, so assume the C99 convention.  If your compiler
// doesn't support this, please provide a patch to extend this ifdef, or
// define MYSQLPP_NO_LONG_LONGS.
typedef unsigned long long ulonglong;
typedef long long longlong;
#endif
#endif // !defined(DOXYGEN_IGNORE)

#if !defined(MYSQLPP_NO_UNSIGNED_INT_TYPES)
/// \brief Contraction for 'unsigned long'
///
/// This is not to be used within the library or directly by end-user
/// code.  It exists to make the MySQL C API headers happy: my_global.h
/// defines it, but we can't use it in MySQL++, so we do it ourselves.
typedef unsigned long ulong;
#endif

} // end namespace mysqlpp

// The MySQL headers define these macros, which is completely wrong in a
// C++ project.  Undo the damage.
#undef min
#undef max

#endif // !defined(DOXYGEN_IGNORE)


// Now that we've defined all the stuff above, we can pull in the full
// MySQL header.  Basically, the above largely replaces MySQL's my_global.h
// while actually working with C++.  This is why we disobey the MySQL
// developer docs, which recommend including my_global.h before mysql.h.
#if defined(MYSQLPP_MYSQL_HEADERS_BURIED)
#	include <mysql/mysql.h>
#else
#	include <mysql.h>
#endif

#endif // !defined(MYSQLPP_COMMON_H)

Changes to doc/userman/common.xsl.



1



2

3




4




5





6


7

8


9
























































































10
11
12






13
14










15
16



































































































17


<?xml version="1.0" encoding="utf-8"?>





<!-- XSL stylesheet containing things common to both HTML and FO




     transformations. -->










<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">


  <xsl:param name="section.autolabel" select="1"/>

  <xsl:param name="section.autolabel.max.depth" select="2"/>


  <xsl:param name="toc.section.depth" select="2"/>

























































































  <!-- Hack to let us get <mathphrase>-like behavior in DB 4.2 -->
  <!-- From: http://www.sagehill.net/docbookxsl/Math.html -->






  <xsl:template match="phrase[@role = 'math']">
    <xsl:call-template name="inline.italicseq"/>










  </xsl:template>
</xsl:stylesheet>




































































































>
>
|
>
>
>

>
|
>
>
>
>
|
>
>
>
>

>
>
>
>
>
|
>
>
|
>
|
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
|
|
>
>
>
>
>
>
|
|
>
>
>
>
>
>
>
>
>
>
|
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
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
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
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
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
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
/***********************************************************************
 dbdriver.cpp - Implements the DBDriver class.

 Copyright (c) 2005-2007 by Educational Technology Resources, Inc.
 Others may also hold copyrights on code in this file.  See the
 CREDITS file in the top directory of the distribution for details.

 This file is part of MySQL++.

 MySQL++ is free software; you can redistribute it and/or modify it
 under the terms of the GNU Lesser General Public License as published
 by the Free Software Foundation; either version 2.1 of the License, or
 (at your option) any later version.

 MySQL++ is distributed in the hope that it will be useful, but WITHOUT
 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
 License for more details.

 You should have received a copy of the GNU Lesser General Public
 License along with MySQL++; if not, write to the Free Software
 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
 USA
***********************************************************************/

#define MYSQLPP_NOT_HEADER
#include "dbdriver.h"

#include "exceptions.h"

#include <sstream>
#include <memory>

// An argument was added to mysql_shutdown() in MySQL 4.1.3 and 5.0.1.
#if ((MYSQL_VERSION_ID >= 40103) && (MYSQL_VERSION_ID <= 49999)) || (MYSQL_VERSION_ID >= 50001)
#	define SHUTDOWN_ARG ,SHUTDOWN_DEFAULT
#else
#	define SHUTDOWN_ARG
#endif

using namespace std;

namespace mysqlpp {

DBDriver::DBDriver() :
is_connected_(false)
{
	mysql_init(&mysql_);
}


DBDriver::DBDriver(const DBDriver& other) :
is_connected_(false)
{
	copy(other);
}


DBDriver::~DBDriver()
{
	if (connected()) {
		disconnect();
	}

	OptionList::const_iterator it;
	for (it = applied_options_.begin(); it != applied_options_.end(); ++it) {
		delete *it;
	}
}


bool
DBDriver::connect(const char* host, const char* socket_name,
		unsigned int port, const char* db, const char* user,
		const char* password)
{
	// Drop previous connection, if any
	if (connected()) {
		disconnect();
	}

	// Set defaults for connection options.  User can override these
	// by calling set_option() before connect().
	set_option_default(new ReadDefaultFileOption("my"));

	// Establish the connection
	return is_connected_ =
			mysql_real_connect(&mysql_, host, user, password, db,
			port, socket_name, mysql_.client_flag);
}


bool
DBDriver::connect(const MYSQL& other)
{
	// Drop previous connection, if any
	if (connected()) {
		disconnect();
	}

	// Set defaults for connection options.  User can override these
	// by calling set_option() before connect().
	set_option_default(new ReadDefaultFileOption("my"));

	// Establish the connection
	return is_connected_ =
			mysql_real_connect(&mysql_, other.host, other.user,
			other.passwd, other.db, other.port, other.unix_socket,
			other.client_flag);
}


void
DBDriver::copy(const DBDriver& other)
{
	if (other.connected()) {
		connect(other.mysql_);
	}
	else {
		is_connected_ = false;
	}
}


void
DBDriver::disconnect()
{
	mysql_close(&mysql_);
	is_connected_ = false;
}


bool
DBDriver::enable_ssl(const char* key, const char* cert,
		const char* ca, const char* capath, const char* cipher)
{
#if defined(HAVE_MYSQL_SSL_SET)
	return mysql_ssl_set(&mysql_, key, cert, ca, capath, cipher) == 0;
#else
	return false;
#endif
}


DBDriver&
DBDriver::operator=(const DBDriver& rhs)
{
	copy(rhs);
	return *this;
}


string
DBDriver::query_info()
{
	const char* i = mysql_info(&mysql_);
	return i ? string(i) : string();
}


bool
DBDriver::set_option(unsigned int o, bool arg)
{
	// If we get through this loop and n is 1, only one bit is set in
	// the option value, which is as it should be.
	int n = o;
	while (n && ((n & 1) == 0)) {
		n >>= 1;
	}
	
	if ((n == 1) && 
			(o >= CLIENT_LONG_PASSWORD) && 
			(o <= CLIENT_MULTI_RESULTS)) {
		// Option value seems sane, so go ahead and set/clear the flag
		if (arg) {
			mysql_.client_flag |= o;
		}
		else {
			mysql_.client_flag &= ~o;
		}

		return true;
	}
	else {
		// Option value is outside the range we understand, or caller
		// erroneously passed a value with multiple bits set.
		return false;
	}
}


std::string
DBDriver::set_option(Option* o)
{
	std::ostringstream os;
	std::auto_ptr<Option> cleanup(o);

	switch (o->set(this)) {
		case Option::err_NONE:
			applied_options_.push_back(o);
			cleanup.release();
			break;

		case Option::err_api_limit:
			os << "Option not supported by database driver v" <<
					client_version();
			throw BadOption(os.str(), typeid(*o)); // mandatory throw!

		case Option::err_api_reject:
			os << "Database driver failed to set option";
			break;

		case Option::err_connected:
			os << "Option can only be set before connection is established";
			break;
	}

	return os.str();
}


bool
DBDriver::shutdown()
{
	return mysql_shutdown(&mysql_ SHUTDOWN_ARG);
}


bool
DBDriver::thread_aware() const
{
#if defined(MYSQLPP_PLATFORM_WINDOWS) || defined(HAVE_PTHREAD) || defined(HAVE_SYNCH_H)
	// Okay, good, MySQL++ itself is thread-aware, but only return true
	// if the underlying C API library is also thread-aware.
	return mysql_thread_safe();
#else
	// MySQL++ itself isn't thread-aware, so we don't need to do any
	// further tests.  All pieces must be thread-aware to return true.
	return false;	
#endif
}

} // end namespace mysqlpp

Changes to doc/userman/fo.xsl.


1


2

3

4


5



































































































































































6




7


8







9






10

































































11


12



13



14


15







































































16



17



18

































































































































































































































































19


20




21


22


23



24



25






26
27

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


56

57






























58

59






60

61









62

63











64



















































65

66








67

68

















69

70







71











































<?xml version="1.0" encoding="utf-8"?>




<!-- XSL stylesheet containing additions to the standard DocBook

     XSL-FO stylesheet.


-->








































































































































































<xsl:stylesheet


		xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 







		xmlns:fo="http://www.w3.org/1999/XSL/Format"






		version="1.0">

































































	


	<!-- Import the standard DocBook stylesheet that this one is based on.



	     We use a web URL, but the local XML catalog should resolve this to



			 the local copy of the stylesheet, if it exists. -->


	<xsl:import href="http://docbook.sourceforge.net/release/xsl/current/fo/docbook.xsl"/>











































































	<!-- Bring in local changes common to both HTML and FO output -->



	<xsl:include href="common.xsl"/>




































































































































































































































































	<!-- Add page breaks before each sect1, and define a processing




	     instruction that will let us add additional hard breaks when


			 needed.  From "DocBook XSL: The Complete Guide" 3/e -->


	<xsl:attribute-set name="section.level1.properties">



		<xsl:attribute name="break-before">page</xsl:attribute>



	</xsl:attribute-set>






	<xsl:template match="processing-instruction('hard-pagebreak')">
		<fo:block break-before='page'/>

	</xsl:template>







































































































































































































































































































































































	<!-- Suppress ulinks from the DocBook from making hyperlinks in the
	  PDF, because most of them are relative links to the refman, and
	  these don't work correctly within a PDF.  If you want cross-links,
	  use the HTML manuals.  This code is from Bob Stayton, on the
	  docbook-apps mailing list. -->
	<xsl:template match="ulink" name="ulink">
		<xsl:choose>



			<xsl:when test="count(child::node())=0">

				<xsl:call-template name="hyphenate-url">



					<xsl:with-param name="url" select="@url"/>

				</xsl:call-template>

			</xsl:when>


			<xsl:otherwise>
				<xsl:apply-templates/>

			</xsl:otherwise>


		</xsl:choose> 






	</xsl:template>










	<!-- Disable hyphenation.  The hyphenation patterns aren't installed


	     as part of FOP, and we don't want it anyway. -->



	<xsl:template name="set.flow.properties">

		<xsl:attribute name="hyphenate">false</xsl:attribute>
	</xsl:template>



















































































	<!-- Rag-right lines -->













































	<xsl:attribute-set name="root.properties">


		<xsl:attribute name="text-align">left</xsl:attribute>

	</xsl:attribute-set>
































	<!-- Use a smaller font for code listings to increase the chances






	     that they can fit on a single sheet, to reduce FOP complaints

			 about being forced to split a listing across pages. -->









	<xsl:attribute-set name="monospace.verbatim.properties">

		<xsl:attribute name="font-size">85%</xsl:attribute>











	</xsl:attribute-set>





















































	<!-- Turn on extensions in DocBook stylesheets which make it use








	     code that FOP 0.9x likes better.  Doesn't affect anything with

			 the 1.69.1 stylesheets we're using on EL5, but is said to help

















			 with 1.72 at least. -->

	<xsl:param name="fop1.extensions" select="1"/>







</xsl:stylesheet>










































>
|
>
>

>
|
>
|
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

>
>
>
>
|
>
>
|
>
>
>
>
>
>
>
|
>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
>
|
>
>
>
|
>
>
>
|
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

>
>
>
|
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

>
>
|
>
>
>
>
|
>
>
|
>
>
|
>
>
>
|
>
>
>
|
>
>
>
>
>
>
|
|
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

<
|
|
|
|
|
|
>
>
>
|
>
|
>
>
>
|
>
|
>
|
>
>
|
|
>
|
>
>
|
>
>
>
>
>
>
|
>
>
>
>
>
>
>

>
>
|
>
>
|
>
>
>
|
>
|
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
>
|
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

>
|
>
>
>
>
>
>
|
>
|
>
>
>
>
>
>
>
>
>
|
>
|
>
>
>
>
>
>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

>
|
>
>
>
>
>
>
>
>
|
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
|
>
>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
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
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
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
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
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
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
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
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
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
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
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
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008

1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
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
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
2.0.3, 2005.08.25 (r1060)

	o Visual C++ makemake system updated to build both debug and
	  release versions of library DLL.

	o Fixed bug in simple1 example that caused crashes on Windows.

	o Doing UTF-8 to ANSI text translation in simple examples now.

	o Previous two releases built libmysqlpp with wrong soname on
	  autotools-based systems.  Fixed.


2.0.2, 2005.08.18 (r1050)

	o Fixes to makemake system for cmd.exe.

	o Fixed the case where the system's C++ library includes an slist
	  implementation in namespace std.


2.0.1, 2005.08.17 (r1046)

	o Added new simple1 example, showing how to retrieve just one
	  column from a table.  Old simple1 is now called simple2, and
	  simple2 is likewise shifted to simple3.

	o Added custom6 example, showing how to do the same thing with
	  SSQLS.

	o Updated user manual to cover new examples.

	o Was accidentally shipping Subversion crap with tarball.  Fixed.


2.0.0, 2005.08.16 (r1031) The "Excess Hair Removal" release

	THIS IS NOT A DROP-IN REPLACEMENT FOR MySQL++ v1.7!

	At minimum, you will have to recompile your program against
	this library.  You may also have to make code changes.
	Please see the "Incompatible Library Changes" chapter of
	the user manual for a guide to migrating your code to this
	new version:

	http://tangentsoft.net/mysql++/doc/userman/html/breakages.html

	o The library's shared object file name (soname) scheme has
	  changed.  (This mainly affects POSIX systems.)
	  
	  The soname for the last 1.7.x releases of MySQL++ was
	  libmysqlpp.so.4, meaning the fourth version of the library's
	  application binary interface (ABI).  (The first ABI version
	  in this scheme was that provided by 1.7.9.)  MySQL++
	  2.0.0's soname is libmysqlpp.so.2.0.0.  Since the dynamic
	  linker setup on some systems will create a symlink to
	  that file called libmysqlpp.so.2, it's possible that this
	  library could be confused with that for MySQL++ 1.7.19
	  through .21, which also used this number.  Do not install
	  this library on a system which still has binaries linked
	  against that version of the library!

	  The new scheme is {ABI}.{feature}.{bug fix}.  That is,
	  the first number changes whenever we break the library's
	  binary interface; the second changes when adding features
	  that do not break the ABI; and the last changes when the
	  release contains only internal bug fixes.  This means
	  that we will probably end up with MySQL++ 3.0 and 4.0 at
	  some point, so there will be further soname conflicts.
	  Hopefully we can put these ABI changes off long enough
	  to avoid any real problems.

	o autoconf now installs headers into $prefix/include/mysql++,
	  instead of $prefix/include.  If you were using the
	  --includedir configure script option to get this behavior
	  before, you no longer need it.

	o Linux binary RPMs will henceforth include only the
	  libmysqlpp.so.X.Y.Z file, and create any short names
	  required, to allow multiple versions to be installed at
	  once.  Currently, you cannot install two MySQL++ library
	  RPMs at once, because they both have /usr/lib/libmysqlpp.so.X,
	  for instance.

	o Replaced the Visual C++ and Borland C++ project files with
	  a new "makemake" system, which creates Makefiles specific
	  to a particular toolchain.  This new mechanism also supports
	  MinGW and generic GCC-on-*ix.  This was done partly to reduce
	  the number of places we have to change when changing the
	  file names in MySQL++ or adding new ones, and partly so we're
	  not tied to one particular version of each of these tools.

	o VC++ Makefiles create a DLL version of the library only
	  now, so there's no excuse for LGPL violations now.
	  This same mechanism should make DLL builds under other
	  Windows compilers easy.

	o Added Connection::enable_ssl(), which enables encrypted
	  connections to the database server using SSL.

	o Connection::create_db() and drop_db() now return true on
	  success, not false.

	o Connection::create_db() and drop_db() use Query::exec()
	  now, for efficiency, rather than Query::execute().

	o Removed Connection::infoo().  Apparently just there to
	  save you from a typo when calling the info() method, since
	  it was a mere alias.

	o Renamed Connection::real_connect() to connect(), gave
	  several more of its parameters defaults, and removed old
	  connect() function.  Then changed user manual and examples
	  to use new APIs.

	o Replaced Connection::read_option() with new set_option()
	  mechanism.  The name change matches the method's purpose
	  better.  Functional changes are that it returns true on
	  success instead of 0, it supports a broader set of options
	  than read_option() did, and it enforces the correct option
	  argument type.

	o You can now call Connection::set_option() before the
	  connection is established, which will simply queue the option
	  request up until the connection comes up.  If you use this
	  feature, you should use exceptions, because that's the only
	  way an option setting failure can be signalled in this case.

	o Removed query-building functions (exec*(), store*(),
	  use()) from class Connection, and moved all the implementation
	  code to class Query.  Query no longer delegates the final
	  step of sending the query to the database server to
	  Connection().

	o Added Connection::enable_ssl(), for turning on SSL support on
	  a connection.

	o Extracted exception disabling mechanism out of the many
	  classes that had the feature into a new OptionalExceptions
	  base class, which all classes having this feature now
	  derive from.  Also, removed all per-method exception
	  handling flags.  Finally, added NoExceptions class.  With
	  all of these changes, there is now a common way to disable
	  exceptions with fine granularity on all objects that
	  support the feature.

	o All custom MySQL++ exceptions now derive from the new
	  Exceptions class.  This regularizes the exception interface
	  and allows you to use a single catch() block if you want.

	o The "throw exceptions" flag is passed from parent to child
	  in all situations now.  (Or if not, please report it as
	  a bug.) This fulfills a promise made in the v1.7.9 user
	  manual, with the cost being that some programs will see
	  new exceptions thrown that they're not expecting.

	o Added a bunch of new exception types: BadOption,
	  ConnectionFailed, DBSelectionFailed, EndOfResults,
	  EndOfResultSets, LockFailed, and ObjectNotInitialized.
	  Some of these replace the use of BadQuery, which in v1.7.x
	  was a kind of generic exception, thrown when something more
	  specific wasn't available.  Beware, this means that programs
	  may start crashing after recompiling them under v2.0 due to
	  uncaught exceptions, if they were only trying to catch BadQuery.

	  There are additional instances where the library will
	  throw new exceptions.  One is when calling a method that
	  forces the internals to use an out-of-bounds index on a
	  vector; previously, this would just make the program
	  likely to crash.  Another is that the library uses the
	  BadFieldName exception -- created in v1.7.30 -- in more
	  apropos situations.

	o Renamed SQLQueryNEParms to BadParamCount, to match naming
	  style of other concrete exception types.

	o Extracted lock()/unlock() functions from Connection and
	  Query classes into a new Lockable interface class.  Locking
	  is implemented in terms of a different class hierarchy, Lock,
	  which allows multiple locking strategies with a single ABI.

	o Removed ResUse::eof().  It's based on a deprecated MySQL
	  C API feature, and it isn't needed anyway.

	o Removed arrow operator (->) for iterator returned by Fields,
	  Result and Row containers.  It was inherently buggy, because
	  a correct arrow operator must return the address of an
	  object, but the underlying element access functions in these
	  classes (e.g. at()) return objects by value, of necessity.
	  Therefore, this operator could only return the address of
	  a temporary, which cannot be safely dereferenced.

	o Returned Row subscripting to something more like the
	  v1.7.9 scheme: there are two operator[] overloads, one for an
	  integer (field by index) and another for const char* (field
	  by name).  lookup_by_name() has been removed.  Because row[0]
	  is ambiguous again, added Row::at() (by analogy with STL
	  sequence containers), which always works.

	o Collapsed two of the Row::value_list*() overloads into
	  two other similar functions using default parameters.
	  This changes the API, but the removed functions aren't
	  used within the library, and I doubt they are used outside,
	  either.

	o Merged RowTemplate into Row.

	o Merged SQLQuery class into Query class.

	o Query is now derived from std::ostream instead of
	  std::stringstream, and we manage our own internal string
	  buffer.

	o Moved SQLParseElement and SQLQueryParms into their own
	  module, qparms.

	o Added multiple result set handling to Query.	MySQL 4.1
	  and higher allow you to give multiple SQL statements in a
	  single "store" call, which requires extensions to MySQL++
	  so you can iterate through the multiple result sets.	Also,
	  stored procedures in MySQL 5.0 reportedly return multiple
	  result sets.	Thanks for the initial patch go to Arnon Jalon;
	  I reworked it quite a bit.

	o Query::storein*() now supports more varieties of the
	  nonstandard slist comtainer.	(Singly-linked version of
	  STL std::list.)

	o Template query mechanism and user manual had several
	  mismatches.  Made manual match actual behavior, or
	  made library match documented behavior, as apropriate.
	  Initial patch by Jürgen MF Gleiss, with corrections and
	  enhancements by Warren Young.

	o Collapsed mysql_* date and time base classes' methods and
	  data into the subclasses.  Also, DateTime no longer derives
	  from Date and Time; you could get away with that in the
	  old hierarchy, but now it creates an inheritance diamond,
	  and allows unsupported concepts like comparing a Time to
	  a DateTime.

	o Removed "field name" form of Row::field_list().  It was
	  pretty much redundant -- if you have the field names, why
	  do you need a list of field names?

	o ColData can convert itself to bool now.  Thanks for this
	  patch go to Byrial Jensen.

	o Removed simp_list_b type; wasn't being used, and doesn't
	  look to be useful for end-user code.

	o Several methods that used to take objects by value now
	  do so by const reference, for efficiency.

	o Several variable and function renamings so that MySQL++
	  isn't needlessly tied to MySQL.  Even if we never make
	  the library work with other database servers, there's
	  little point in tying this library to MySQL blindly.

	o Renamed all private data members of MySQL++ classes to
	  have trailing underscores.

	o 'private' section follows 'public' section in all classes
	  now.

	o Removed mysql++.hh and sqlplus.hh backwards-compatibility
	  headers.

	o Added copy ctors to Date/Time classes so that they will
	  work in SSQLS under GCC 4.0.0.  Without these, the compiler
	  couldn't make the conversion from raw MySQL row data.

	o Fixed a bunch of GCC 4.0 pedantic warnings: added virtual
	  dtors to all base classes, calling base class ctors from leaf
	  classes, etc.

	o All warnings fixed under VC++ at warning level 3.  (Mostly
	  harmless signedness and integer conversion stuff.)

	o Updated LGPL license/copyright comments at the top of
	  several files to use FSF's new physical address.

	o Relicensed user manual under a close variant of the Linux
	  Documentation Project License, as it's designed for
	  documentation, which the LGPL is not.  Permission for this
	  received from Kevin Atkinson and MySQL AB.

	o Added ABI and API breakages chapter to user manual.  It
	  is basically a subset of this ChangeLog, with only the
	  information an end-user must know when migrating between
	  versions.

	o Reworked user manual's DocBook code quite a bit after
	  reading Bob Stayton's book "DocBook XSL" 3/e.  Better handling
	  of stylesheets, taking advantage of some superior DocBook
	  features, prettier output (especially the HTML version), etc.

	o Rewrote doc/userman/README to make it clearer how to get
	  started contributing to the user manual.  It's essentially a
	  "getting started with DocBook" guide now!

	o Lots of small text improvements to user and reference
	  manuals.  Aside from the obvious tracking of library changes,
	  made a bunch of minor style and clarity improvements.

	o Added CSS stylesheets for userman and refman to
	  make the HTML versions of each a) not ugly; and b) match
	  tangentsoft.net.  (Yes, some may say that these are incompatible
	  goals....)

	o Standardized exception handling code in the examples that
	  use it.

	o Fixed a potential memory leak due to exceptions thrown from
	  ResUse.  Thanks for this patch go to Chris Frey.

	o Using new "no exceptions" feature of library in simple1
	  example, so it is now truly simple.

	o simple1 example no longer depends as much on util module, so
	  that all of the important code is in one place.  Makes
	  learning MySQL++ a little less intimidating.

	o Added new simple2 and usequery examples, to demonstrate
	  the proper way to handle a "use" query, with exceptions
	  disabled, and not, respectively.  Added them to the user
	  manual, in the appropriate place.

	o Refactored the "print stock table" example functions
	  again, to make code using them clearer.

	o UTF-8 to UCS-2 handling in examples is now automatic on
	  Windows.

	o Removed debug code from Windows Unicode output examples
	  that slipped into previous release.

	o resetdb example is now clearer, and more robust in the
	  face of database errors.

	o Simplified connect_to_db() in examples' util module.

	o Added sample autoconf macro for finding MySQL++ libraries, for
	  people to use in their own autotools-based projects.

	o Lots and lots of minor cleanups not worth mentioning
	  individually...


1.7.40, 2005.05.26 (r719)

	o Multiple item form of insert() now works if you're using the
	  SQLQuery class, or its derivative, Query.  Thanks to Mark
	  Meredino for this patch.

	o Fixed a bug in const_string::compare(), in which MySQL++
	  would walk off the end of the shorter of the two strings.
	  All was well if the two were the same length.

	o ResUse::operator=() now fully updates the object, so it's more
	  like the behavior of the full ctor.

	o All source files now contain a license and copyright statement
	  somewhere within them.

	o Optimized mysql++.h a bit: it now #includes only the minimum set
	  of files required, and there is now an idempotency guard.
	  This improves compile times a smidge, but mainly it was
	  done to clean up the generated #include file graph in the
	  reference manual.  Before, it was a frightful tangle because
	  we #included everything except custom*.h.

	o Constness fix in MySQL++ date/time classes to avoid compiler
	  warnings with SSQLS.	Thanks to Wolfram Arnold for this patch.

	o Fixed some compiler warnings in custom*.h.  Thanks to Chris Frey
	  for this patch.

	o Added "Submitting Patches" and "Maintaining a Private CVS
	  Repository" sections to the HACKERS file.  Thanks to Chris
	  Frey for the source material for these sections.  The HACKERS
	  file was improved in several other ways at the same time.

	o PDF version of user manual no longer has links to the reference
	  manual.  They were ugly, and they were broken anyway due to the
	  way we move the PDFs after generating them.  If you want
	  interlinked manuals, use the HTML version.

	o PDF version of user manual now has hard page breaks between
	  chapters.

	o Removed complic1 example.  Wasn't pulling its own weight.
	  Everything it is supposed to demonstrate is shown in other
	  examples already.

	o Refactored print_stock_table() in examples/util module to be
	  four functions, and made all the examples use various of
	  these functions where appropriate.  Before, several of
	  the examples had one-off stock table printing code because
	  print_stock_table() wasn't exactly the right thing, for one
	  reason or another.  One practical problem with this is that
	  some of the examples missed out on the recent Unicode updates;
	  now such a change affects all examples the same way.

	o Since so many of the examples rely on the util module, the user
	  manual now covers it.  The simple1 example in the user manual
	  didn't make much sense before, in particular, because it's
	  really just a driver for the util module.

	o Added custom5 example.  It shows how to use the equal_list()
	  functionality of SSQLS.  Thanks to Chris Frey for the original
	  version of this program.  (I simplified it quite a bit after
	  accepting it.)

	o New user manual now covers the value_list(), equal_list() and
	  field_list() stuff that the old manual covered but which was
	  left out in previous versions of the new manaul.  Most of the
	  examples are the same, but the prose is almost completely new.
	  This new section includes the custom5 example.

	o Every declaration in MySQL++ is now documented in the reference
	  manual, or explicitly treated as "internal only".

	o Improved docs for MySQL++'s mechanism to map between MySQL
	  server types and C++ types.  Initial doc patch by Chris Frey,
	  which I greatly reworked.

	o Improved a lot of existing reference manual documentation while
	  adding the new stuff.

	o Expanded greatly on the exception handling discussion in the user
	  manual.

	o Added all-new "Quoting and Escaping" section to the user
	  manual's Tutorial chapter.  Moved some existing comments on
	  quoting and escaping around and added some new ones to other
	  sections as a result.

	o Added all-new "Handling SQL Nulls" section to the user manual's
	  Tutorial chapter.

	o Many improvements to the Overview section of the user manual.

	o Row::operator[] reference now explains the right and wrong way to
	  use the values it returns.  This is in response to a mailing list
	  post where someone was incorrectly using this feature and getting
	  a bunch of dangling pointers.

	o Updated Doxyfile so 1.3.19.1 parses it without warnings.  Still
	  works with versions back to 1.2.18, at least.  (These are
	  the versions shipped with Fedora Core 3 and Red Hat Linux 9,
	  respectively.)

	o Using a superior method to make Doxygen ignore certain sections
	  of the source code.  Between this change and the fact that
	  everything not so ignored is documented, Doxygen no longer
	  generates any warnings.

	o Lots of code style updates.  Everything should now be consistently
	  formatted.


1.7.35, 2005.05.05 (r601) The "Cinco de Mayo" release

	o Added a "how to use Unicode with MySQL++" chapter to the user
	  manual.  (Too bad "Cinco de Mayo" doesn't have any accented
	  characters.  That would be just _too_ precious.)

	o VC++ examples now use the Unicode Win32 APIs, so they can display
	  Unicode data from MySQL++.

	o Added an optional conversion function to examples/util.cpp to
	  handle the conversion from UTF-8 to UCS-2 on Win32.

	o Moved "brief history of MySQL++" from intro section of refman to
	  intro section of userman.

	o Lots of small bits of documentation polishing.
	
	o Made some minor constness fixes.  Thanks to Erwin van Eijk
	  for this patch.

	o Made some warning fixes for GCC 4.0.	Not all warnings are
	  fixed, because some of the needed changes would break the ABI.
	  Thanks to Chris Frey for this patch.

	o Added lib/Doxyfile to distribution.
	

1.7.34, 2005.04.30 (r573)

	o Added a multiple-insert method for Query, which lets you insert
	  a range of records from an STL container (or the whole thing,
	  if you like) in a single SQL query.  This is faster, and it
	  reduces coding errors due to less repetition.  Thanks to Mark
	  Meredino for the patch.

	o Reference and user manual now get rebuilt automatically when
	  required.  (E.g. on 'make dist', or explicitly now through 'make
	  docs'.)

	o Made it easier to change the maximum number of SSQLS data members
	  in generated custom-macros.h file.  It used to be hard-coded in
	  several places in lib/custom.pl; now it's a variable at the top of
	  the file.

	o Changed default SSQLS data member limit to 25, which is what it
	  has been documented as for a long time now.  It was actually 26
	  within custom.pl.

	o Fixed a regression in previous version.

	o Trimmed some fat from the distribution packages.

	o Some more small doucmentation improvements.


1.7.33, 2005.04.29 (r555)

	o Worked around an overloaded operator lookup bug in VC++ 7.1
	  that caused SSQLS insert, replace and update queries to get
	  mangled.  (Symptom was that custom2 and custom3 examples didn't
	  work right.)  Thanks to Mark Meredino for digging up the
	  following, which explains the problem and gives the solution:

	  http://groups-beta.google.com/group/microsoft.public.vc.stl/browse_thread/thread/9a68d84644e64f15

	o Some VC++ warning fixes.

	o Major documentation improvements:
	
		o Using DocBook for user manual and Doxygen for reference
		  manual.  The former now references the latter where
		  useful.

		o Split out HACKERS and CREDITS files from main README,
		  and improved remaining bits of README.

		o Moved the text from the old v1.7.9 LaTeX-based
		  documentation over into the new systems, and reworked
		  it to more closely resemble English.

		o Added a lot of new material to documentation, and
		  simplified a lot of what already existed.

		o Documentation is now being built in HTML and PDF forms.

	o ebuild file updated to take advantage of recent configure script
	  features.  Thanks to Chris Frey for this patch.



1.7.32, 2005.03.10 (r479)

	o Example building may now be skipped with --disable-examples
	  configure script flag.

	o Changed stock items added in resetdb.  One is now UTF-8 encoded,
	  to show that basic use of Unicode with MySQL++ is easy, yet not
	  foolproof.  (See formatting of table on systems where cout isn't
	  UTF-8 aware!)  Other stock items now follow a theme, for your
	  amusement.  :)

	o custom3 example now changes UTF-8 item's name to the 7-bit ASCII
	  equivalent.  Previously, this example would fix a spelling error
	  in the table.

	o resetdb example now says 'why' when it is unable to create the
	  sample database.

	o Small formatting change to print_stock_table(), used by several
	  examples.

	o Was issuing a VC++-specific warning-disable pragma when built by
	  any Windows compiler.  Fixed.
	

1.7.31, 2005.03.05 (r462) The "Inevitable Point-one Followup" release

	o Check for threads support must now be explicitly requested via
	  configure script's new --enable-thread-check flag.

	o Fix for contacting MySQL server on a nonstandard port number.
	  Thanks to Chris Frey for this patch.

	o Example programs using standard command line format now accept a
	  fourth optional parameter, a port number for the server.  Thanks
	  to Chris Frey for this patch.

	o One more g++ 3.4 pedantic warning fix by Chris Frey.

	o Exception handling in resetdb is no longer nested, because you'd
	  get a segfault on some systems when an exception was thrown from
	  one of the inner try blocks.

	o Improvements to Connection class's handling of locking mechanism.
	  Concept based on patches by Rongjun Mu.

	o Implemented the declared-but-never-defined Query::lock().  Thanks
	  to Rongjun Mu for this patch.
	
	o Cleaned up some unclear if/else blocks in connection.cpp by
	  adding explicit braces, correct indenting and putting normal
	  code path in the if side instead of the else.


1.7.30, 2005.02.28 (r443) The "Power of Round Numbers" release

	o bootstrap script now accepts a 'pedantic' argument, which sets a
	  bunch of CFLAGS that make g++ very picky about the code it
	  accepts without warnings.
	  
	o Fixed a bunch of things that generated warnings with g++ in
	  pedantic mode. Only two warnings remain, having to do with
	  floating point comparisons.  (See Wishlist for plans on how to
	  deal with these.)  Thanks to Chris Frey for this patch.

	o Split long tests out of configure.in into M4 files in new config
	  subdir.  This makes configure.in easier to read.

	o Added preliminary thread support.  Currently, this just means that
	  we detect the required compiler and linker thread flags, and link
	  against the proper thread-safe libraries.  THERE MAY BE
	  UN-THREAD-SAFE CODE IN MYSQL++ STILL!

	o Standard C++ exceptions are the default now.  Old pre-Standard
	  exception stuff removed.

	o Row::lookup_by_name() will throw the new BadFieldName exception if
	  you pass a bad field name.  Thanks for this patch to Chris Frey.

	o Row::operator[] will throw a Standard C++ out of bounds exception
	  by way of std::vector::at() if you pass it a bad index.  Thanks
	  for this patch to Chris Frey.

	o Setting Connection::is_connected flag to false on close().
	  Previously, is_connected() would continue to return true after
	  close() was called.

	o All number-to-string conversion ctors in SQLString class now use
	  ostringstream to do the conversion.  Previously, we used
	  snprintf(), which isn't available on all systems.  Also, we used a
	  C99 format specifier for the "long long" conversion, which is also
	  not available on all systems.  This new ostringstream code should
	  be platform-independent, finally.


1.7.28, 2005.02.04 (r403)

	o --with-mysql* flags to configure script now try the given
	  directory explicitly, and only if that fails do they try
	  variations, like tacking '/lib' and such onto it to try and find
	  the MySQL includes and libraries.  Thanks to Matthew Walton for
	  the patch.

	o Finally removed sql_quote.h's dependence on custom.h, by moving
	  the one definition it needed from custom.h to deps.h.  This will
	  help portability to compilers that can't handle the SSQLS macros,
	  by making that part of the library truly optional.


1.7.27, 2005.01.12 (r395)

	o configure check for libmysqlclient now halts configuration if the
	  library isn't found.  Previously, it would just be flagged as
	  missing, and MySQL++ would fail to build.

	o Added sql_string.cpp to VC++ and BCBuilder project files.

	o Removed Totte Karlsson's 'populate' example, which never made it
	  into the distribution anyway.

	o Removed last vestiges of 'dummy.cpp'.

	o Renamed *.cc to *.cpp in BCBuilder project files.

	o Worked around a BCBuilder C++ syntax processing bug in row.h.


1.7.26, 2004.12.17 (r382)

	o Moved all of the SQLString definitions out of the header and into
	  a new .cpp file, reformatted it all, and made the integer
	  conversion functions use snprintf() or _snprintf() instead of
	  sprintf().  Also, widened some of the buffers for 64-bit systems.

	o Using quoted #include form for internal library headers, to avoid
	  some problems with file name clashes.  (The headers should still
	  be installed in their own separate directory for best results,
	  however.)  Thanks to Chris Frey and Evan Wies for the patch and
	  the discussion that lead to it.

	o Removed unnecessary semicolons on namespace block closures.
	  Thanks to Evan Wies for this patch.

	o Fixed namespace handling in the legacy headers mysql++.hh and
	  sqlplus.hh.  Thanks to Chris Frey for this patch.

	o #including iostream instead of ostream in lib/null.h for
	  broader C++ compatibility.  (This may allow MySQL++ to work on GCC
	  2.95.2 again, but this is unconfirmed.)

	o Detecting proper mysql_shutdown() argument handling automatically
	  in platform.h for the Windows compiler case instead of making the
	  user edit the file.  Thanks to Evan Wies for this patch.
	
	o Fixed examples/Makefile.simple to use new *.cpp file naming.

	o Fix to Gentoo ebuild file's exception configure switch handling.
	  Thanks to Chris Frey for this patch.

	o Rebuilding lib/custom*.h intelligently now, to avoid unnecessary
	  recompiles after running bootstrap script.


1.7.25, 2004.12.09 (r360)

	o Yet more fixes to the --with-mysql-lib and --with-mysql-include
	  flags.

	o Added DLLEXPORT stuff to platform.h, hopefully so that someone
	  can figure out how to make VC++ make a DLL version of MySQL++.

	o Renamed *.cc to *.cpp.

	o Made 'set -> myset' change in VC++ project files.

	o Some style changes (mostly whitespace) in header files.


1.7.24, 2004.12.08 (r343)

	o Fixed the --with-mysql-lib and --with-mysql-include flags'
	  behavior, and extended their search ability to handle one other
	  common case.  (Fixed by Steve Roberts)

	o Fixes to put freestanding functions in namespace mysqlpp.  (They
	  weren't in the namespace, while all the class member functions
	  were.)  This required bumping the ABI version number to 4.
	  
	o Renamed set module to myset, to avoid conflicts with Standard C++
	  Library's set.h when MySQL++ headers were installed into one of
	  the standard system include directories.

	o Renamed all the idempotency guards to make them consistent in
	  style and unique to MySQL++.

	o Reformatted all of lib/*.cc.


1.7.23, 2004.11.20 (r333)

	o Query::reset() now empties the stored query string.  If you
	  subsequently stored a longer query in the object, you'd overwrite
	  the previous query, but otherwise the longer part of the previous
	  one would stick out past the new query.

	o We now look to the NO_LONG_LONGS macro only to decide whether to
	  fake 64-bit integer support using 32-bit integers.

	o 64-bit integer support under Visual C++ may be working now, using
	  that platform's __int64_t type.  This has not been tested.

	o Removed 64-bit integer support for Codewarrior on Mac OS 9 and
	  earlier.  OS X uses GCC, so it requires no special support.

	o Added MinGW detection in platform.h.
	
	o If you pass a flag (-X) to the examples that take the standard
	  parameters (resetdb, simple1, etc.), it prints a usage message.
	
	o Better error handling in resetdb example, where errors are the
	  most critical.  (If that one runs without errors, the others
	  probably will, too, and you have to run that one first.)

	o resetdb now reports success, rather than succeeding silently.

	o Removed the code in sample1 example that duplicated util module's
	  print_stock_table(), and called that function instead.

	o Moved the preview() calls in the example programs to before the
	  query execution calls, because execution modifies the query.

	o All examples that take the standard command line parameters now 
	  exit when connect_to_db() fails in one of the ways that don't
	  throw an exception, rather than bulling onward until the next
	  MySQL database call fails because the connection isn't up.

	o dbinfo example now takes the standard command line parameters.

	o Much better output formatting in dbinfo example.

	o Calling reset() where appropriate in the various example programs.
	  Before, the programs may have worked, but not for the right
	  reason.  This lead some people to believe that calling reset()
	  was not necessary.

	o Fixed an incorrect use of row["string"] in complic1 example.

	o Lots of code style improvements to the examples.

	o Some VC++ type warnings squished.  Some remain.
	

1.7.22, 2004.11.17 (r302)

	o Applied patches by Zahroof Mohammed to allow it to build under GCC
	  3.4.2.  Tested on MinGW and Fedora Core 3 systems.

	o Removed all the forward declarations in defs.h, and added
	  forward declarations where necessary in individual header files.
	  #including defs.h in fewer locations as a result.

	o Legacy headers sqlplus.hh and mysql++.hh now declare they are
	  using namespace mysqlpp, to allow old code to compile against the
	  new library without changes.

	o Removed query_reset parameter from several class Query member
	  functions.  In the implementation, these parameters were always
	  overridden!  No sense pretending that we pay attention to these
	  parameters.  This changes the ABI version to 3.

	o #including custom.h in sql_query.h again...it's necessary on GCC
	  3.4.
	
	o bootstrap script runs lib/config.pl after configure.  This is
	  just a nicety for those running in 'maintainer mode'.


1.7.21, 2004.11.05 (r273)

	o Generating a main mysql++ RPM containing just the library files
	  and basic documentation, and the -devel package containing
	  everything else.

	o Devel package contains examples now, along with a new Makefile
	  that uses the system include and library files, rather than the
	  automake-based Makefile.am we currently have which uses the files
	  in the mysql++ source directory.

	o Renamed sqlplusint subdirectory in the package to lib.

	o Removed the obsolete lib/README file.

	o lib/sql_query.h no longer #includes custom.h, simplifying
	  build-time dependencies and shortening compile times.


1.7.20, 2004.11.03 (r258)

	o Collapsed all numbered *.hh headers into a single *.h file.  For
	  example, the contents of row1.hh, row2.hh and row3.hh are now in
	  row.h.

	o While doing the previous change, broke several circular
	  dependencies.  (The numbered file scheme was probably partly done
	  to avoid this problem.)  The practical upshot of most of these
	  changes is that some functions are no longer inline.

	o Removed define_short.hh and everything associated with it.  The
	  library now uses the short names exclusively (e.g. Row instead of
	  MysqlRow).

	o Put all definitions into namespace mysqlpp.  For most programs,
	  simply adding a 'using namespace mysqlpp' near the top of the
	  program will suffice to convert to this version.

	o Once again, the main include file was renamed, this time to
	  mysql++.h.  Hopefully this is the last renaming!

	o mysql++.hh still exists.  It emits a compiler warning that the
	  file is obsolete, then it #includes mysql++.h for you.

	o sqlplus.hh is back, being a copy of the new mysql++.hh.  Both of
	  these files may go away at any time.  They exist simply to help
	  people transition to the new file naming scheme.

	o Renamed mysql++-windows.hh to platform.h, and added code to it to
	  handle #inclusion of config.h on autotools-based systems
	  intelligently.  This fixes the config.h error when building under
	  Visual C++.

	o There is now only one place where conditional inclusion of
	  winsock.h happens: platform.h.

	o Beautified the example programs.


1.7.19, 2004.10.25 (r186)

	o Fixed an infinite loop in the query mechanism resulting from the
	  strstream change in the previous version.  There is an overloaded
	  set of str() member functions that weren't a problem when query
	  objects were based on strstream.
	 
	o Query mechanism had a bunch of const-incorrectness: there were
	  several function parameters and functions that were const for
	  the convenience of other parts of the code, but within these
	  functions the constness was const_cast away!  This was evil
	  and wrong; now there are fewer const promises, and only one is
	  still quietly broken within the code.  (It's in the SQLQuery
	  copy ctor implementation; it should be harmless.)

	o Removed operator=() in Query and SQLQuery classes.  It cannot take
	  a const argument for the same reason we have to cast away const
	  in the SQLQuery copy ctor.  It's tolerable to do this in the copy
	  ctor, but intolerable in an operator.  Since the copy ctor is good
	  enough for all code within the library and within my own code, I'm
	  removing the operator.

	o Above changes required bumping the ABI to version 2.

	o Visual C++ projects now look for MySQL build files in c:\mysql,
	  since that's the default install location.  (Previously, it was
	  c:\program files\mysql.)


1.7.18, 2004.10.01 (r177)

	o Changed all the strstream (and friends) stuff to stringstream type
	  classes.  Let there be much rejoicing.

	o Query object now lets you use store() even when the SQL query
	  cannot return a result, such as a DROP TABLE command.  This is
	  useful for sending arbitrary SQL to the server.  Thanks to
	  Jose Mortensen for the patch.

	o Quote fix in configure.in, thanks to David Sward.

	o Renamed undef_short file to undef_short.hh.

	o Gentoo ebuild file is actually being shipped with the tarball,
	  instead of just sitting in my private CVS tree since 1.7.14 was
	  current.  Ooops....


1.7.17, 2004.09.16 (r170)

	o Reverted one of the VC++ warning fix changes from 1.7.16 that
	  caused crashes on Linux.

	o Added a configure test that conditionally adds the extra 'level'
	  parameter to mysql_shutdown() that was added in MySQL 4.1.3 and
	  5.0.1.


1.7.16, 2004.09.13 (r160)

	o Building VC++ version with DLL version of C runtime libraries, and
	  at warning level 3 with no warnings emitted.

	o VC++ build no longer attempts to fake "long long" support.  See
	  the Wishlist for further thoughts on this.


1.7.15, 2004.09.02 (r144)

	o Renamed Configure file to common.am, to avoid file name conflict
	  with configure script on case-sensitive file systems.

	o Added ebuild file and ebuild target to top-level Makefile for
	  Gentoo systems.  Thanks to Chris Frey for this.

	o Small efficiency improvements to BadQuery exception handling.
	  Initial idea by Chris Frey, improvements by Warren Young.


1.7.14, 2004.08.26 (r130)

	o Builds with Visual C++ 7.1.

	o Fixed a bug in custom macro generation that caused problems with
	  GCC 3.4.  (X_cus_value_list ctor definition was broken.)


1.7.13, 2004.08.23 (r92)

	o Removed USL CC support.  (System V stock system compiler.)  Use
	  GCC on these platforms instead.

	o Added examples/README, explaining how to use the examples, and
	  what they all do.

	o Most of the example programs now accept command line arguments for
	  host name, user name and password, like resetdb does.

	o Renamed sinisa_ex example to dbinfo.

	o Several Standard C++ syntax fixes to quash errors emitted by
	  GCC 3.4 and Borland C++ Builder 6.  Thanks to Steffen Schumacher
	  and Totte Karlsson for their testing and help with these.

	o Added proper #includes for BCBuilder, plus project files for same.
	  Thanks to Totte Karlsson for these.


1.7.12, 2004.08.19 (r63)

	o Many Standard C++ fixes, most from the GCC 3.4 patch by
	  Rune Kleveland.

	o Added Wishlist file to distribution.

	o Fixed a problem in the bootstrap script that caused complaints
	  from the autotools on some systems.

	o RPM building is working properly now.


	o Fixed the idempotency guard in datetime1.hh.


1.7.11, 2004.08.17 (r50)

	o Renamed mysql++, defs and define_short files, adding .hh to the
	  end of each.  (They're header files!)  This shouldn't impact
	  library users, since these are hopefully used internal to the
	  library only.

	o Removed sqlplus.hh file.  Use mysql++.hh instead.
	
	o Added mysql++.spec, extracted from contributed 1.7.9 source RPM, 
	  and updated it significantly.  Also, added an 'rpm' target to
	  Makefile.am to automate the process of building RPMs.

	o Added bootstrap and LGPL files to distribution tarball.

	o Added pre-1.7.10 history to this file.

	o Removed .version file.  Apparently it's something required by old
	  versions of libtool.


1.7.10, 2004.08.16 (r27)

	o Maintenance taken over by Warren Young (mysqlpp at etr dash usa
	  dot com.) See http://lists.mysql.com/plusplus/3326 for details.

	o Applied many of the GCC 3.x patches submitted for 1.7.9 over
	  the years.  This allows it to build on everything from 3.0 to
	  3.3.3, at least.  Because so many patches are rolled up in one
	  big jump, it's difficult to describe all the changes and where
	  they came from.  Mostly they're Standard C++ fixes, as GCC
	  has become more strict in the source code that it will accept.

	o MysqlRow used to overload operator[] for string types as well as
	  integers so you could look up a field by its name, rather than by
	  its index.  GCC 3.3 says this is illegal C++ due to ambiguities in
	  resolving which overload should be used in various situations.
	  operator[] is now overloaded only for one integer type, and a
	  new member function lookup_by_name() was added to maintain the old
	  by-field-name functionality.

	o Fixed another operator overloading problem in SSQLS macro
	  generation with GCC 3.3.

	o The _table member of SSQLS-defined structures is now const char*,
	  so you can assign to it from a const char* string.

	o Got autoconf/automake build system working with current versions
	  of those tools again.  Removed the generated autotools files from
	  CVS.

	o Renamed library file from libsqlplus to libmysqlpp.


1.7.9 (May 1 2001) Sinisa Milivojevic <sinisa@mysql.com>

    * Fixed a serious bug in Connection constructor when reading MySQL
    * options
    * Improved copy constructor and some other methods in Result /
    * ResUse
    * Many other minor improvements
    * Produced a complete manual with chapter 5 included
    * Updated documentation, including a Postscript format

1.7.8 (November 14 2000) Sinisa Milivojevic <sinisa@mysql.com>

    * Introduced a new, standard way of dealing with C++ exceptions.
    * MySQL++ now supports two different methods of tracing exceptions.
    * One is by the fixed type (the old one) and one is standard C++
    * type by the usage of what() method. A choice of methods has to be
    * done in building a library. If configure script is run with
    * -enable-exception option , then new method will be used. If no
    * option is provided, or -disable-exception is used, old MySQL++
    * exceptions will be enforced. This innovation is a contribution of
    * Mr. Ben Johnson <ben@blarg.net>
    * MySQL++ now automatically reads at connection all standard MySQL
    * configuration files
    * Fixed a bug in sql_query::parse to enable it to parse more then 99
    * char's
    * Added an optional client flag in connect, which will enable usage
    * of this option, e.g. for getting matched and not just affected
    * rows. This change does not require any changes in existing
    * programs
    * Fixed some smaller bugs
    * Added better handling of NULL's. Programmers will get a NULL
    * string in result set and should use is_null() method in ColData to
    * check if value is NULL
    * Further improved configuration
    * Updated documentation, including a Postscript format

1.7.6 (September 22 2000) Sinisa Milivojevic <sinisa@mysql.com>

    * This release contains some C++ coherency improvements and scripts
    * enhacements
    * result_id() is made available to programmers to fetch
    * LAST_INSERT_ID() value
    * Connection constroctur ambiguity resolved, thanks to marc@mit.edu
    * Improved cnnfigure for better finding out MySQL libraries and
    * includes
    * Updated documentation, including a Postscript format

1.7.5 (July 30 2000) Sinisa Milivojevic <sinisa@mysql.com>

    * This release has mainl bug fixes  and code improvements
    * A bug in FieldNames::init has been fixed, enabling a bug free
    * usage of this class with in what ever a mixture of cases that is
    * required
    * Changed behaviour of ResUse, Result and Row classes, so that they
    * could be re-used as much as necessary, without any memory leaks,
    * nor with any re-initializations necessary
    * Fixed all potential leaks that could have been caused by usage of
    * delete instead of delete[] after memory has been allocated with
    * new[]
    * Deleted all unused classes and macros. This led to a reduction of
    * library size to one half of the original size. This has
    * furthermore brought improvements in compilation speed
    * Moved all string manipulation from system libraries to
    * libmysqlclient, thus enabling uniformity of code and usage of 64
    * bit integers on all platforms, including Windows, without
    * reverting to conditional compilation. This changes now requires
    * usage of mysql 3.23 client libraries, as mandatory
    * Changed examples to reflect above changes
    * Configuration scripts have been largely changed and further
    * changes shall appear in consecutive sub-releases. This changes
    * have been done and shall be done by our MySQL developer Thimble
    * Smith <tim@mysql.com>
    * Changed README, TODO and text version of manual. Other versions of
    * manual have not been updated
    * Fixed .version ``bug''. This is only partially fixed and version
    * remains 1.7.0 due to some problems in current versions of libtool.
    * This shall be finally fixed in a near future
    * Several smaller fixes and improvements
    * Added build.sh script to point to the correct procedure of
    * building of this library. Edit it to add configure options of your
    * choice

1.7 (May17 2000) Sinisa Milivojevic <sinisa@mysql.com>

    * This is mainly a release dealing with bug fixes, consistency
    * improvements and easier configure on some platforms
    * A bug in fetch_row() method of ResUse class has been fixed. Beside
    * changes that existed in a distributed patch, some additional error
    * checking has been introduced
    * A bug in escape manipulator has been fixed that could cause an
    * error if all characters had to be escaped
    * An inconsistency in column indexing has been fixed. Before this
    * version, column names in row indexing with strings, i.e.
    * row[<string>] , has been case sensitive, which was inconsistent
    * with MySQL server handling of column names
    * An inconsistency in conversion from strings to integers or floats
    * has been fixed. In prior version a space found in data would cause
    * a BadConversion exception. This has been fixed, but 100%
    * consistency with MySQL server has not been targeted, so that other
    * non-numeric characters in data will still cause BadConversion
    * exception or error. As this API is used in applications, users
    * should provide feedback if full compatibility with MySQL server is
    * desired, in which case BadConversion exception or error would be
    * abolished in some of future versions
    * A new method in ColData class has been introduced. is_null()
    * method returns a boolean to denote if a column in a row is NULL.
    * Finally, as of this release, testing for NULL values is possible.
    * Those are columns with empty strings for which is_null() returns
    * true.
    * Some SPARC Solaris installations had C++ exception problems with
    * g++ 2.95.2 This was a bug that was fixed in GNU gcc, as from
    * release 2.95 19990728. This version was thoroughly tested and is
    * fully functional on SPARC Solaris 2.6 with the above version of
    * gcc.
    * A 'virtual destructor ' warning for Result class has been fixed
    * Several new functions for STL strings have been added. Those
    * functions (see string_util.hh) add some of the functionality
    * missing in existing STL libraries
    * Conversion for 64 bit integers on FreeBSD systems has been added.
    * On those systems _FIX_FOR_BSD_ should be defined in CXXFLAGS prior
    * to configuring. Complete conversion to the usage of functions for
    * integer conversion found in mysqlclient library is planned for one
    * of the next releases
    * A completely new, fully dynamic, dramatic and fully mutable result
    * set has been designed and will be implemented in some of 2.x
    * releases
    * Several smaller fixes and improvements, including defaulting
    * exceptions to true, instead of false, as of this version
    * An up-to-date and complete Postscript version of documentation is
    * included in this distribution
    * Large chunks of this manual are changed, as well as README and
    * TODO files.

1.6 (Feb 3 2000) Sinisa Milivojevic <sinisa@mysql.com>

    * This is a major release as it includes new features and major
    * rewrites
    * Automatic quoting and escaping with streams. It works
    * automatically , depending on the column type. It will work with <<
    * on all ostream derived types. it is paricularly handy with query
    * objects and strstreams. Automatic quoting and escaping on cout,
    * cerr and clog stream objects is intentionally left out, as quoting
    * / escaping on those stream objects is not necessary. This feature
    * can be turned of by setting global boolean dont_quote_auto to
    * true.
    * Made some major changes in code, so that now execute method should
    * be used only with SSQL and template queries, while for all other
    * query execution of UPDATE's, INSERT's, DELETE's, new method exec()
    * should be used. It is also faster.
    * New method get_string is inroduced for easier handling / casting
    * ColData into C++ strings.
    * Major rewrite of entire code, which led to it's reduction and
    * speed improvement. This also led to removal of several source
    * files.
    * Handling of binary data is introduced. No application program
    * changes are required. One of new example programs demonstrates
    * handling of binary data
    * Three new example programs have been written and thoroughly
    * tested. Their intention is to solve some problems addressed by
    * MySQL users.
    * Thorough changes is Makefile system has been made
    * Better configuration scripts are written, thanks to D.Hawkins
    * <dhawkins@cdrgts.com>
    * Added several bug fixes
    * Changed Manual and Changelog

1.5 (Dec 1 1999) Sinisa Milivojevic <sinisa@mysql.com>

    * Fixed bug in template queries, introduced in 1.4 (!)
    * Fixed connect bug
    * Fixed several bug in type_info classes
    * Added additional robustness in classes
    * Added additional methods for SQL type info
    * Changed Changelog and README

1.4 (Nov 25 1999) Sinisa Milivojevic <sinisa@mysql.com>

    * Fixed bug in store and storein methods
    * Fixed one serious memory leak
    * Fixed a very serious bug generated by gcc 2.95.xx !!
    * Added robustness in classes, so that e.g. same query and row
    * objects can be re-used
    * Changed sinisa_ex example to reflect and demonstrate this
    * stability
    * Changed Changelog and README
    * Few other bug fixes and small improvements and speed-ups

1.3 (Nov 10 1999) Sinisa Milivojevic <sinisa@mysql.com>

    * Fixed several erronous definitions
    * Further changed source to be 2.95.2 compatible
    * Expunged unused statements, especially dubious ones, like use of
    * pointer_tracker
    * Corrected bug in example file fieldinf1
    * Finally fixed mysql_init in Connection constructor, which provided
    * much greater stability !
    * Added read and get options, so that clients, like mysqlgui can use
    * it
    * Changed Changelog and README
    * Many other bug fixes.

1.2 (Oct 15 1999) Sinisa Milivojevic <sinisa@mysql.com>

    * First offical release. Version 1.0 and 1.1 were releases by Sinisa
    * before I (Kevin Atkinson) made him the offical maintainer,
    * Many manual fixes.
    * Changed README and Changelog
    * Changed source to be compilable by gcc 2.95.xx, tribute to Kevin
    * Atkinson <kevinatk@home.com>
    * Added methods in Connection class which are necessary for
    * fullfilling administrative functions with MySQL
    * Added many bug fixes in code pertaining to missing class
    * initializers , as notified by Michael Rendell <michael@cs.mun.ca>
    * Sinisa Milivojevic <sinisa@mysql.com> is now the offical
    * maintainer.

1.1 (Aug 2 1999) Sinisa Milivojevic <sinisa@mysql.com>

    * Added several bug fixes
    * Fixed memory leak problems and variables overlapping problems.
    * Added automake and autoconf support by loic@ceic.com
    * Added Makefile for manual
    * Added support for cygwin
    * Added example sinisa_ex (let modesty prevail) which used to crash
    * a lot when memory allocation, memory leak and overlap problems
    * were present. Smooth running of this example proves that all those
    * bugs are fixed
    * Corrected bugs in sql_query.cc regarding delete versus delete[]
    * and string length in manip.cc
    * Changed manual
    * Changed README
    * Many other smaller things

1.0 (June 9 1999) Michael Widenius <monty@monty.pp.sci.fi>

    * Added patches from Orion Poplawski <orion@bvt.com> to support the
    * UnixWare 7.0 compiler

.64.1.1a (Sep 27 1998)

    * Fixed several bugs that caused my library to fail to compile with
    * egcs 1.1. Hopefully it will still compile with egcs 1.0 however I
    * have not been able to test it with egcs 1.0.
    * Removed some problem causing debug output in sql++pretty.

.64.1a (Aug 1 1998)

    * Added an (almost) full guide to using Template Queries.
    * Fixed it so the SQLQuery will throw an exception when all the
    * template parameters are not provided.
    * Proofread and speedchecked the manual (it really needed it).
    * Other minor document fixes.

.64.0.1a (July 31 1998)

    * Reworked the Class Reference section a bit.
    * Minor document fixes
    * Added more examples for SSQLS.
    * Changed the syntax of equal_list for SSQLS from equal_list (cchar
    * *, Manip, cchar *) to (cchar *, cchar *, Manip).
    * Added set methods to SSQLS. These new methods do the same thing as
    * there corresponding constructors.
    * Added methods for creating a mysql_type_info from a C++ type_info.

.64.a (July 24 1998)

    * Changed the names of all the classes so they no longer have to
    * have Mysql in the begging of it. However if this creates a problem
    * you can define a macro to only use the old names instead.
    * The Specialized SQL Structures (formally known as Custom Mysql
    * Structures) changed from mysql_ to sql_.
    * Added the option of using exceptions thoughout the API.
    * ColData (formally known as MysqlStrings) will now throw an
    * exception if there is a problem in the conversion.
    * Added a null adapter.
    * Added Mutable Result Sets
    * Added a very basic runtime type identification for SQL types
    * Changed the document format from POD to LYX .
    * Am now using a modified version of Perceps to extract the class
    * information directly from the code to make my life easier.
    * Added an option of defining a macro to avoid using the automatic
    * conversion with binary operators.
    * Other small fixed I probully forgot to mentune.

.63.1.a

    * Added Custom Mysql Structures.
    * Fixed the Copy constructor of class Mysql
    * Started adding code so that class Mysql lets it children now when
    * it is leaving
    * Attempted to compile it into a library but still need help. As
    * default it will compile as a regular program.
    * Other small fixes.

.62.a (May 3 1998)

    * Added Template Queries
    * Created s separate SQLQuery object that is independent of an SQL
    * connection.
    * You no longer have to import the data for the test program as the
    * program creates the database and tables it needs.
    * Many small bug fixes.

.61.1.a (April 28 1998)

    * Cleaned up the example code in test.cc and included it in the
    * manual.
    * Added an interface layout plan to the manual.
    * Added a reverse iterator.
    * Fixed a bug with row.hh (It wasn't being included because of a
    * typo).

.61.0.a

    * Major interface changes. I warned you that the interface may
    * change while it is in pre-alpha state and I wasn't kidding.
    * Created a new and Separate Query Object. You can no longer execute
    * queries from the Mysql object instead you have to create a query
    * object with Mysql::query() and use it to execute queries.
    * Added the comparison operators to MysqlDate, MysqlTime and
    * MysqlDateTime. Fixed a few bugs in the MysqlDate... that effected
    * the stream output and the conversion of them to strings.
    * Reflected the MysqlDate... changes in the manual.
    * Added a new MysqlSet object and a bunch of functions for working
    * with mysql set strings.

.60.3a (April 24 1998)

    * Changed strtoq and strtouq to strtoll and strtull for metter
    * compatibility Minor Manual fix.
    * Changed makefile to make it more compatible with Solaris (Thanks
    * Chris H)
    * Fixed bug in comparison functions so that they would compare in he
    * right direction.
    * Added some items to the to do list be sure to have a look.

Changes to doc/userman/fo2pdf.

1

2



3

4




5




6





7


8

9

10
11


12
13

14






15



16



17
18


19














20








21

22

23
24

25
26


27

28






29
30

31
32



33

34
35

36
37





38
39
#!/bin/bash

AHCMD=/usr/XSLFormatterV42/run.sh



FOPCMD=$(type -p fop)

XEPCMD=/usr/local/xep/xep









FOFILE=$1





PDFFILE=$2


if [ -n "$FOFILE" -a -r "$FOFILE" -a -n "$PDFFILE" ]

then

	if [ -x "$XEPCMD" ]
	then


		echo Rendering $FOFILE to $PDFFILE with RenderX XEP...
		$XEPCMD -quiet -fo $FOFILE -pdf $PDFFILE

	elif [ -x "$AHCMD" ]






	then



		echo Rendering $FOFILE to $PDFFILE with Antenna House XSL Formatter...



		$AHCMD -silent -d $FOFILE -o $PDFFILE
	elif [ -x "$FOPCMD" ]


	then














		echo "Rendering $FOFILE to $PDFFILE with Apache FOP ($FOPCMD)..."








		$FOPCMD -q -fo $FOFILE $PDFFILE

	else

		echo 'Cannot find a working XSL-FO processor on your system!  See'
		echo 'doc/usrman/README.txt for instructions on installing one.'

		echo
		exit 1


	fi

else






	if [ -n "$FOFILE" ]
	then

		echo "XSL-FO file $FOFILE does not exist."
		echo



	fi

	echo "usage: $0 fofile pdffile"
	echo

	echo '    Translates XSL-FO in fofile to PDF output in pdffile.'
	echo





	exit 1
fi
|
>
|
>
>
>
|
>
|
>
>
>
>

>
>
>
>
|
>
>
>
>
>
|
>
>
|
>
|
>
|
|
>
>
|
|
>
|
>
>
>
>
>
>
|
>
>
>
|
>
>
>
|
<
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
|
>
|
>
|
|
>
|
<
>
>
|
>
|
>
>
>
>
>
>
|
|
>
|
|
>
>
>
|
>
|
|
>
|
|
>
>
>
>
>
|
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
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
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88

89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
/***********************************************************************
 transaction.cpp - Implements the Transaction class.

 Copyright © 2006-2014 by Educational Technology Resources, Inc.
 Others may also hold copyrights on code in this file.  See the
 CREDITS.txt file in the top directory of the distribution for details.

 This file is part of MySQL++.

 MySQL++ is free software; you can redistribute it and/or modify it
 under the terms of the GNU Lesser General Public License as published
 by the Free Software Foundation; either version 2.1 of the License, or
 (at your option) any later version.

 MySQL++ is distributed in the hope that it will be useful, but WITHOUT
 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
 License for more details.

 You should have received a copy of the GNU Lesser General Public
 License along with MySQL++; if not, write to the Free Software
 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
 USA
***********************************************************************/

#define MYSQLPP_NOT_HEADER
#include "common.h"

#include "transaction.h"

#include "connection.h"
#include "query.h"

using namespace std;
using namespace mysqlpp;


//// ctors /////////////////////////////////////////////////////////////

Transaction::Transaction(Connection& conn, bool consistent) :
conn_(conn),
finished_(true)		// don't bother rolling it back if ctor fails
{
	// Begin the transaction set
	Query q(conn_.query("START TRANSACTION"));
	if (consistent) {
		q << " WITH CONSISTENT SNAPSHOT";
	}
	q.execute();

	// Setup succeeded, so mark our transaction as not-finished.
	finished_ = false;
}


Transaction::Transaction(Connection& conn, IsolationLevel level,
		IsolationScope scope, bool consistent) :
conn_(conn),
finished_(true)		// don't bother rolling it back if ctor fails
{
	// Set the transaction isolation level and scope as the user wishes
	Query q(conn_.query("SET "));
	if (scope == session) q << "SESSION ";
	if (scope == global)  q << "GLOBAL ";
	q << "TRANSACTION ISOLATION LEVEL ";
	switch (level) {
		case read_uncommitted:	q << "READ UNCOMMITTED"; break;
		case read_committed:	q << "READ COMMITTED";   break;
		case repeatable_read:	q << "REPEATABLE READ";  break;
		case serializable:		q << "SERIALIZABLE";     break;
	}
	q.execute();

	// Begin the transaction set.  Note that the above isn't part of
	// the transaction, on purpose, so that scope == transaction affects
	// *this* transaction, not the next one.
	q << "START TRANSACTION";
	if (consistent) {
		q << " WITH CONSISTENT SNAPSHOT";
	}
	q.execute();

	// Setup succeeded, so mark our transaction as not-finished.
	finished_ = false;
}


//// dtor //////////////////////////////////////////////////////////////


Transaction::~Transaction()
{
	if (!finished_) {
		try {
			rollback();
		}
		catch (...) {
			// eat all exceptions
		}
	}
}


//// commit ////////////////////////////////////////////////////////////

void
Transaction::commit()
{
	conn_.query("COMMIT").execute();
	finished_ = true;
}


//// rollback //////////////////////////////////////////////////////////

void
Transaction::rollback()
{
	conn_.query("ROLLBACK").execute();
	finished_ = true;
}


Changes to doc/userman/html.xsl.

1
2

3
4
5

6
7
8

9
10
11
12
13
14


15
16
17
18
19
20
21
22
23
24
25
26
27
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

56


57



58
59
60
61
62
63
64
65

66
67
68
69
70


71

72




73
74
75
76
77
78
79
80
81
82
83
84
85


86
87
88
89


90
91
92

93
94
95
96
97
98
99
100
101

<?xml version="1.0" encoding="utf-8"?>


<!-- XSL stylesheet containing additions to the standard DocBook
     chunked-HTML stylesheet.
-->


<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
		version="1.0">

	
	<!-- Import the standard DocBook stylesheet that this one is based on.
	     We use a web URL, but the local XML catalog should resolve this to
			 the local copy of the stylesheet, if it exists. -->
	<xsl:import href="http://docbook.sourceforge.net/release/xsl/current/html/chunk.xsl"/>



	<!-- Bring in local changes common to both HTML and FO output -->
	<xsl:include href="common.xsl"/>

	<!-- The DocBook stylesheets use ISO 8859-1 by default, even when the
	     XML files are marked UTF-8.  If you serve such files from a web
			 server that advertises UTF-8 content, browsers display the page
			 incorrectly, because they believe the web server. -->
	<xsl:output method="html" encoding="UTF-8" indent="no"/>

	<!-- HTML-specific XSL parameters -->
	<xsl:param name="chunk.fast" select="0"/>
	<xsl:param name="html.stylesheet" select="'tangentsoft.css'"/>
	<xsl:param name="use.id.as.filename" select="1"/>



	<!-- Special ulink types, to reduce boilerplate link code -->


	<xsl:template match="ulink" name="refman_ulink">
		<xsl:choose>
			<!-- type=mysqlapi: makes hyperlinks to MySQL C API reference manual,
			     given only the function name with dashes instead of underscores
					 as the URL. -->
			<xsl:when test="@type = 'mysqlapi'">
				<tt>
					<a>
						<xsl:variable name="fn_dash" select="@url"/>
						<xsl:variable name="fn_name"
							select="translate($fn_dash, '-', '_')"/>
						<xsl:attribute name="href">
							<xsl:text>http://dev.mysql.com/doc/mysql/en/</xsl:text>
							<xsl:value-of select="$fn_dash"/>
							<xsl:text>.html</xsl:text>
						</xsl:attribute>

						<xsl:value-of select="$fn_name"/>
						<xsl:text>()</xsl:text>
					</a>


				</tt>
			</xsl:when>




			<!-- type=classref: makes hyperlinks to a class in the MySQL++
			     reference manual, given its name. -->
			<xsl:when test="@type = 'classref'">
				<tt>

					<a>


						<xsl:attribute name="href">



							<xsl:text>../refman/classmysqlpp_1_1</xsl:text>
							<xsl:value-of select="@url"/>
							<xsl:text>.html</xsl:text>
						</xsl:attribute>
						<xsl:choose>
							<xsl:when test="count(child::node())=0">
								<xsl:value-of select="@url"/>
							</xsl:when>

							<xsl:otherwise>
								<xsl:apply-templates/>
							</xsl:otherwise>
						</xsl:choose>
					</a>


				</tt>

			</xsl:when>





			<!-- type=structref: makes hyperlinks to a struct in the MySQL++
			     reference manual, given its name. -->
			<xsl:when test="@type = 'structref'">
				<tt>
					<a>
						<xsl:attribute name="href">
							<xsl:text>../refman/structmysqlpp_1_1</xsl:text>
							<xsl:value-of select="@url"/>
							<xsl:text>.html</xsl:text>
						</xsl:attribute>
						<xsl:choose>
							<xsl:when test="count(child::node())=0">


								<xsl:value-of select="@url"/>
							</xsl:when>
							<xsl:otherwise>
								<xsl:apply-templates/>


							</xsl:otherwise>
						</xsl:choose>
					</a>

				</tt>
			</xsl:when>

			<xsl:otherwise>
				<xsl:call-template name="ulink"/>
			</xsl:otherwise>
		</xsl:choose>
	</xsl:template>
</xsl:stylesheet>

<
|
>
|
|
<
>

|
|
>
|
|
<
<
<

>
>
|
|

|
|
|
<
<
|
<
<
<
<

>
>
|
>
>
|
<
<
|
|
|
|
|
|
|
|
|
|
|
<
|
>
|
<
<
>
>
|
<
>
>
>
|
|
|
|
|
>
|
>
>
|
>
>
>
|
|
<
|
|
<
<
<
>
|
<
|
<
<
>
>
|
>
|
>
>
>
>

|
<
<
<
<
|
|
|
|
|
<
<
>
>
|
|
|
|
>
>
|
<
<
>
|
<
|
|
<
<
<
<
|
>

1
2
3
4

5
6
7
8
9
10
11



12
13
14
15
16
17
18
19
20


21




22
23
24
25
26
27
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
56
57
58
59
60
61
62
63

64
65



66
67

68


69
70
71
72
73
74
75
76
77
78
79




80
81
82
83
84


85
86
87
88
89
90
91
92
93


94
95

96
97




98
99

/***********************************************************************
 store_if.cpp - Demonstrates Query::store_if(), showing only the rows
	from the sample table with prime quantities.  This isn't intended
	to be useful, only to show how you can do result set filtering that

	outstrips the power of SQL.

 Copyright (c) 2005-2007 by Educational Technology Resources, Inc.
 Others may also hold copyrights on code in this file.  See the CREDITS
 file in the top directory of the distribution for details.

 This file is part of MySQL++.




 MySQL++ is free software; you can redistribute it and/or modify it
 under the terms of the GNU Lesser General Public License as published
 by the Free Software Foundation; either version 2.1 of the License, or
 (at your option) any later version.

 MySQL++ is distributed in the hope that it will be useful, but WITHOUT
 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public


 License for more details.





 You should have received a copy of the GNU Lesser General Public
 License along with MySQL++; if not, write to the Free Software
 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
 USA
***********************************************************************/



#include "util.h"
#include "stock.h"

#include <mysql++.h>

#include <iostream>

#include <math.h>


// Define a functor for testing primality.

struct is_prime
{
	bool operator()(const stock& s)


	{
		if ((s.num == 2) || (s.num == 3)) {
			return true;	// 2 and 3 are trivial cases

		}
		else if ((s.num < 2) || ((s.num % 2) == 0)) {
			return false;	// can't be prime if < 2 or even
		}
		else {
			// The only possibility left is that it's divisible by an
			// odd number that's less or equal to its square root.
			for (int i = 3; i <= sqrt(double(s.num)); i += 2) {
				if ((s.num % i) == 0) {
					return false;
				}
			}
			return true;
		}
	}
};



int
main(int argc, char *argv[])



{
	try {

		// Connect to the sample database


		mysqlpp::Connection con;
		if (!connect_to_db(argc, argv, con)) {
			return 1;
		}

		// Collect the stock items with prime quantities
		std::vector<stock> results;
		mysqlpp::Query query = con.query();
		query.store_if(results, stock(), is_prime());

		// Show the results




		print_stock_header(results.size());
		std::vector<stock>::const_iterator it;
		for (it = results.begin(); it != results.end(); ++it) {
			print_stock_row(it->item.c_str(), it->num, it->weight,
					it->price, it->sdate);


		}
	}
	catch (const mysqlpp::BadQuery& e) {
		// Something went wrong with the SQL query.
		std::cerr << "Query failed: " << e.what() << std::endl;
		return 1;
	}
	catch (const mysqlpp::Exception& er) {
		// Catch-all for any other MySQL++ exceptions


		std::cerr << "Error: " << er.what() << std::endl;
		return 1;

	}





	return 0;
}

Changes to doc/userman/mktxt.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#!/bin/sh
# Script to convert C++ source files to a text format, with 4 spaces for
# every tab, and with the leading block comment removed.  Used to
# reformat the example programs so they can be xincluded directly into
# the DocBook during XSLT processing.

TXTFILE=$1
SRCFILE=`echo ../../examples/$TXTFILE | sed -e s/\\\\.txt/.cpp/`
if [ ! -e $SRCFILE ]
then
	SRCFILE=`echo ../../examples/$TXTFILE | sed -e s/\\\\.txt/.h/`
fi
CLINE=`grep -n '\*\*/' $SRCFILE |cut -f1 -d:`
LINE=`echo $CLINE + 2 |bc`

#echo Converting $SRCFILE to $TXTFILE, starting at line $LINE...

expand -t4 $SRCFILE | tail -n +$LINE > $TXTFILE

<
<
<
<
<

|
<
<
<
<
<
<
<
|
<
|
<
|





1
2







3

4

5






$(RELEASE_LIB_FILE): $(OBJS)







	cd release

	$(LD) $(LDFLAGS) $(LDSTARTUP) $(OBJS) $(LDEXE) $(LIBS)

	cd ..

Changes to doc/userman/xinclude.mod.




1


2






3












4


























































5





6



7









8
9






































































10


11


12








13







































































14












15









16




17













































<!ELEMENT xi:include (xi:fallback?) >


<!ATTLIST xi:include






    xmlns:xi   CDATA       #FIXED    "http://www.w3.org/2001/XInclude"












    href       CDATA       #IMPLIED


























































    parse      (xml|text)  "xml"





    xpointer   CDATA       #IMPLIED



    encoding   CDATA       #IMPLIED 









    accept     CDATA       #IMPLIED
    accept-language CDATA  #IMPLIED >









































































<!ELEMENT xi:fallback ANY>


<!ATTLIST xi:fallback








    xmlns:xi   CDATA   #FIXED   "http://www.w3.org/2001/XInclude" >




















































































<!ENTITY % local.chapter.class "| xi:include">









<!ENTITY % local.divcomponent.mix "| xi:include">




<!ENTITY % local.para.char.mix "| xi:include">










































>
>
>
|
>
>
|
>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
>
>
>
>
|
>
>
>
|
>
>
>
>
>
>
>
>
>
|
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

>
>
|
>
>
|
>
>
>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

>
>
>
>
>
>
>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
|
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
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
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
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
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
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
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
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
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
<?xml version="1.0" encoding='UTF-8'?>
<!DOCTYPE sect1 PUBLIC "-//OASIS//DTD DocBook V4.2//EN"
    "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">

<sect1 id="threads">
  <title>Using MySQL++ in a Multithreaded Program</title>

  <para>MySQL++ is not &#x201C;thread safe&#x201D; in any
  meaningful sense. MySQL++ contains very little code that
  actively prevents trouble with threads, and all of it is
  optional. We have done some work in MySQL++ to make thread
  safety <emphasis>achievable</emphasis>, but it doesn&#x2019;t come
  for free.</para>

  <para>The main reason for this is that MySQL++ is
  generally I/O-bound, not processor-bound. That is, if
  your program&#x2019;s bottleneck is MySQL++, the ultimate
  cause is usually the I/O overhead of using a client-server
  database. Doubling the number of threads will just let your
  program get back to waiting for I/O twice as fast. Since <ulink
  url="http://www.eecs.berkeley.edu/Pubs/TechRpts/2006/EECS-2006-1.pdf">threads
  are evil</ulink> and generally can&#x2019;t help MySQL++, the only
  optional thread awareness features we turn on in the shipping
  version of MySQL++ are those few that have no practical negative
  consequences. Everything else is up to you, the programmer, to
  evaluate and enable as and when you need it.</para>

  <para>We&#x2019;re going to assume that you are reading this chapter
  because you find yourself needing to use threads for some other
  reason than to speed up MySQL access. Our purpose here is limited
  to setting down the rules for avoiding problems with MySQL++ in a
  multi-threaded program. We won&#x2019;t go into the broader issues of
  thread safety outside the scope of MySQL++. You will need a grounding
  in threads in general to get the full value of this advice.</para>

  <sect2 id="thread-build">
    <title>Build Issues</title>

    <para>Before you can safely use MySQL++ with threads, there are
    several things you must do to get a thread-aware build:</para>

    <orderedlist>
      <listitem>
        <para><emphasis>Build MySQL++ itself with thread awareness
        turned on.</emphasis></para>

        <para>On Linux, Cygwin and Unix (OS X, *BSD, Solaris...),
        pass the <computeroutput>--enable-thread-check</computeroutput>
        flag to the <filename>configure</filename> script. Beware, this
        is only a request to the <filename>configure</filename> script
        to look for thread support on your system, not a requirement
        to do or die: if the script doesn&#x2019;t find what it needs
        to do threading, MySQL++ will just get built without thread
        support. See <filename>README-Unix.txt</filename> for more
        details.</para>

        <para>On Windows, if you use the Visual C++ project files or
        the MinGW Makefile that comes with the MySQL++ distribution,
        threading is always turned on, due to the nature of
        Windows.</para>

        <para>If you build MySQL++ in some other way, such as with
        Dev-Cpp (based on MinGW) you&#x2019;re on your own to enable
        thread awareness.</para>
      </listitem>

      <listitem>
        <para><emphasis>Link your program to a thread-aware build of the
        MySQL C API library.</emphasis></para>

        <para>If you use a binary distribution of MySQL on
        Unixy systems (including Cygwin) you usually get
        two different versions of the MySQL C API library,
        one with thread support and one without. These are
        typically called <filename>libmysqlclient</filename> and
        <filename>libmysqlclient_r</filename>, the latter being the
        thread-safe one. (The &#x201C;<filename>_r</filename>&#x201D;
        means reentrant.)</para>

        <para>If you&#x2019;re using the Windows binary distribution
        of MySQL, you should have only one version of the C
        API library, which should be thread-aware. If you have
        two, you probably just have separate debug and optimized
        builds. See <filename>README-Visual-C++.txt</filename> or
        <filename>README-MinGW.txt</filename> for details.</para>

        <para>If you build MySQL from source, you might only get
        one version of the MySQL C API library, and it can have
        thread awareness or not, depending on your configuration
        choices.</para>
      </listitem>

      <listitem>
        <para><emphasis>Enable threading in your program&#x2019;s build
        options.</emphasis></para>

        <para>This is different for every platform, but it&#x2019;s
        usually the case that you don&#x2019;t get thread-aware builds
        by default. Depending on the platform, you might need to change
        compiler options, linker options, or both. See your development
        environment&#x2019;s documentation, or study how MySQL++ itself
        turns on thread-aware build options when requested.</para>
      </listitem>
    </orderedlist>
  </sect2>


  <sect2 id="thread-conn-mgmt">
    <title>Connection Management</title>

    <para>The MySQL C API underpinning MySQL++ does not allow multiple
    concurrent queries on a single connection. You can run into this
    problem in a single-threaded program, too, which is why we cover the
    details elsewhere, in <xref linkend="concurrentqueries"/>.
    It&#x2019;s a thornier problem when using threads, though.</para>

    <para>The simple fix is to just create a separarate <ulink
    url="Connection" type="classref"/> object for each thread that
    needs to make database queries. This works well if you have a small
    number of threads that need to make queries, and each thread uses
    its connection often enough that the server doesn&#x2019;t <link
    linkend="conn-timeout">time out</link> waiting for queries.</para>

    <para>If you have lots of threads or the frequency of queries is
    low, the connection management overhead will be excessive. To avoid
    that, we created the <ulink url="ConnectionPool" type="classref"/>
    class. It manages a pool of <classname>Connection</classname>
    objects like library books: a thread checks one out, uses
    it, and then returns it to the pool as soon as it&#x2019;s
    done with it. This keeps the number of active connections
    low. We suggest that you keep each connection&#x2019;s
    use limited to a single variable scope for <ulink
    url="http://en.wikipedia.org/wiki/RAII">RAII</ulink> reasons;
    we created a little helper called <ulink url="ScopedConnection"
    type="classref"/> to make that easy.</para>

    <para><classname>ConnectionPool</classname> has three
    methods that you need to override in a subclass to
    make it concrete: <methodname>create()</methodname>,
    <methodname>destroy()</methodname>, and
    <methodname>max_idle_time()</methodname>. These overrides let
    the base class delegate operations it can&#x2019;t successfully do
    itself to its subclass. The <classname>ConnectionPool</classname>
    can&#x2019;t know how to <methodname>create()</methodname>
    the <classname>Connection</classname> objects, because that
    depends on how your program gets login parameters, server
    information, etc.  <classname>ConnectionPool</classname>
    also makes the subclass <methodname>destroy()</methodname>
    the <classname>Connection</classname> objects it created; it
    could assume that they&#x2019;re simply allocated on the heap
    with <methodname>new</methodname>, but it can&#x2019;t be sure,
    so the base class delegates destruction, too. Finally, the base
    class can&#x2019;t know which connection idle timeout policy
    would make the most sense to the client, so it asks its subclass
    via the <methodname>max_idle_time()</methodname> method.</para>

    <para><classname>ConnectionPool</classname> also allows you to
    override <methodname>release()</methodname>, if needed. For simple
    uses, it&#x2019;s not necessary to override this.</para>

    <para>In designing your <classname>ConnectionPool</classname>
    derivative, you might consider making it a <ulink
    url="http://en.wikipedia.org/wiki/Singleton_pattern">Singleton</ulink>,
    since there should only be one pool in a program.</para>

    <para>Another thing you might consider doing is passing a
    <ulink url="ReconnectOption" type="classref"/> object to
    <methodname>Connection::set_option()</methodname> in your
    <methodname>create()</methodname> override before returning the
    new <classname>Connection</classname> pointer. This will cause
    the underlying MySQL C API to try to reconnect to the database
    server if a query fails because the connection was dropped
    by the server. This can happen if the DB server is allowed to
    restart out from under your application. In many applications,
    this isn&#x2019;t allowed, or if it does happen, you might want
    your code to be able to detect it, so MySQL++ doesn&#x2019;t set
    this option for you automatically.</para>

    <para>Here is an example showing how to use connection pools with
    threads:</para>

    <programlisting><xi:include href="cpool.txt" parse="text"
    xmlns:xi="http://www.w3.org/2001/XInclude"/></programlisting>

    <para>The example works with both Windows native
    threads and with POSIX threads.<footnote><para>The file
    <filename>examples/threads.h</filename> contains a few macros and
    such to abstract away the differences between the two threading
    models.</para></footnote> Because thread-enabled builds are only
    the default on Windows, it&#x2019;s quite possible for this program
    to do nothing on other platforms. See above for instructions on
    enabling a thread-aware build.</para>

    <para>If you write your code without checks for thread support
    like you see in the code above and link it to a build of MySQL++
    that isn&#x2019;t thread-aware, it will still try to run. The
    threading mechanisms fall back to a single-threaded mode when
    threads aren&#x2019;t available. A particular danger is that the
    mutex lock mechanism used to keep the pool&#x2019;s internal data
    consistent while multiple threads access it will just quietly
    become a no-op if MySQL++ is built without thread support. We do
    it this way because we don&#x2019;t want to make thread support
    a MySQL++ prerequisite. And, although it would be of limited
    value, this lets you use <classname>ConnectionPool</classname>
    in single-threaded programs.</para>

    <para>You might wonder why we don&#x2019;t just work around
    this weakness in the C API transparently in MySQL++ instead of
    suggesting design guidelines to avoid it. We&#x2019;d like to do
    just that, but how?</para>

    <para>If you consider just the threaded case, you could argue for
    the use of mutexes to protect a connection from trying to execute
    two queries at once. The cure is worse than the disease: it turns a
    design error into a performance sap, as the second thread is blocked
    indefinitely waiting for the connection to free up. Much better to
    let the program get the &#x201C;Commands out of sync&#x201D; error,
    which will guide you to this section of the manual, which tells you
    how to avoid the error with a better design.</para>

    <para>Another option would be to bury
    <classname>ConnectionPool</classname> functionality within MySQL++
    itself, so the library could create new connections at need.
    That&#x2019;s no good because the above example is the most complex
    in MySQL++, so if it were mandatory to use connection pools, the
    whole library would be that much more complex to use. The whole
    point of MySQL++ is to make using the database easier. MySQL++
    offers the connection pool mechanism for those that really need it,
    but an option it must remain.</para>
  </sect2>


  <sect2 id="thread-helpers">
    <title>Helper Functions</title>

    <para><classname>Connection</classname> has several thread-related
    static methods you might care about when using MySQL++ with
    threads.</para>

    <para>You can call
    <methodname>Connection::thread_aware()</methodname> to
    determine whether MySQL++ and the underlying C API library were
    both built to be thread-aware. I want to stress that thread
    <emphasis>awareness</emphasis> is not the same thing as thread
    <emphasis>safety</emphasis>: it&#x2019;s still up to you to make
    your code thread-safe. If this method returns true, it just means
    it&#x2019;s <emphasis>possible</emphasis> to achieve thread-safety,
    not that you actually have it.</para>

    <para>If your program&#x2019;s connection-management strategy
    allows a thread to use a <classname>Connection</classname>
    object that another thread created, you need to know
    about <methodname>Connection::thread_start()</methodname>.
    This function sets up per-thread resources needed to make MySQL
    server calls. You don&#x2019;t need to call it when you use the
    simple <classname>Connection</classname>-per-thread strategy,
    because this function is implicitly called the first time you
    create a <classname>Connection</classname> in a thread. It&#x2019;s
    not harmful to call this function from a thread that previously
    created a <classname>Connection</classname>, just unnecessary. The
    only time it&#x2019;s necessary is when a thread can make calls
    to the database server on a <classname>Connection</classname>
    that another thread created and that thread hasn&#x2019;t already
    created a <classname>Connection</classname> itself.</para>

    <para>If you use <classname>ConnectionPool</classname>, you should
    call <methodname>thread_start()</methodname> at the start of each
    worker thread because you probably can&#x2019;t reliably predict
    whether your <methodname>grab()</methodname> call will create a new
    <classname>Connection</classname> or will return one previously
    returned to the pool from another thread.  It&#x2019;s possible
    to conceive of situations where you can guarantee that each pool
    user always creates a fresh <classname>Connection</classname> the
    first time it calls <methodname>grab()</methodname>, but thread
    programming is complex enough that it&#x2019;s best to take the
    safe path and always call <methodname>thread_start()</methodname>
    early in each worker thread.</para>

    <para>Finally, there&#x2019;s the complementary method,
    <methodname>Connection::thread_end()</methodname>. Strictly
    speaking, it&#x2019;s not <emphasis>necessary</emphasis> to call
    this. The per-thread memory allocated by the C API is small,
    it doesn&#x2019;t grow over time, and a typical thread is going
    to need this memory for its entire run time. Memory debuggers
    aren&#x2019;t smart enough to know all this, though, so they will
    gripe about a memory leak unless you call this from each thread
    that uses MySQL++ before that thread exits.</para>

    <para>Although its name suggests otherwise,
    <methodname>Connection::thread_id()</methodname> has nothing to
    do with anything in this chapter.</para>
  </sect2>


  <sect2 id="thread-data-sharing">
    <title>Sharing MySQL++ Data Structures</title>

    <para>We&#x2019;re in the process of making it safer to share
    MySQL++&#x2019;s data structures across threads. Although things
    are getting better, it&#x2019;s highly doubtful that all problems
    with this are now fixed. By way of illustration, allow me explain
    one aspect of this problem and how we solved it in MySQL++
    3.0.0.</para>

    <para>When you issue a database query that returns rows, you
    also get information about the columns in each row. Since the
    column information is the same for each row in the result set,
    older versions of MySQL++ kept this information in the result
    set object, and each <ulink url="Row" type="classref"/> kept
    a pointer back to the result set object that created it so it
    could access this common data at need. This was fine as long as
    each result set object outlived the <classname>Row</classname>
    objects it returned.  It required uncommon usage patterns to run
    into trouble in this area in a single-threaded program, but in
    a multi-threaded program it was easy. For example, there&#x2019;s
    frequently a desire to let one connection do the queries, and other
    threads process the results.  You can see how avoiding lifetime
    problems here would require a careful locking strategy.</para>

    <para>We got around this in MySQL++ v3.0 by giving these shared data
    structures a lifetime independent of the result set object that
    intitially creates it. These shared data structures stick around
    until the last object needing them gets destroyed.</para>

    <para>Although this is now a solved problem, I bring it up because
    there are likely other similar lifetime and sequencing problems
    waiting to be discovered inside MySQL++. If you would like to
    help us find these, by all means, share data between threads
    willy-nilly.  We welcome your crash reports on the MySQL++
    mailing list. But if you&#x2019;d prefer to avoid problems,
    it&#x2019;s better to keep all data about a query within a single
    thread. Between this and the advice in prior sections, you should
    be able to use threads with MySQL++ without trouble.</para>
  </sect2>
</sect1>

Changes to dtest.

1



2
3



4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
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
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80

81
82
83
84
85
86
87
88
89
90
91


92
93
94


95
96
97
98
99
100
101
102
103
104
105
#!/bin/bash




TMP=`mktemp bmXXXXXX`




# Run simple unit tests first.
typeset -i count=0
echo -n 'Running unit tests:'
for t in test_*
do
	if [ -x "$t" ]
	then
		errmsg=`./exrun "$t" 2>&1`
		errno=$?
		if [ "$errno" = 0 ]
		then
			count=count+1
		else
			rm -f $TMP
			echo " $t FAILED ($errno)"
			echo
			echo "$errmsg"
			exit $?
		fi
	fi
done
echo " $count tests succeeded"
echo 'All unit tests passed' >> $TMP


# Assume AUTO_INCREMENT id column in images table will get 1 in
# load_jpeg call below, since we reset the DB before doing it.
export QUERY_STRING=id=1


# Now run examples to test high-level behavior.  The repeated use of
# resetdb is intentional!  It's run after each example that changes
# the database in a way that will cause a subsequent example to fail
# because data it expects isn't present.
echo -n 'Running examples:'
for t in \
	resetdb simple[0-9] store_if for_each multiquery tquery1 \
	resetdb tquery[2-9] \
	resetdb ssqls[0-9] \
	load_jpeg cgi_jpeg
do
	if [ -x $t ]
	then
		if [ "$t" = "resetdb" ]
		then
			echo
			echo -n "   "
		fi
	
		echo -n "$t "



		echo "---------------- BEGIN $t OUTPUT ----------------" >> $TMP
		if ! ./exrun $t -D $* >> $TMP
		then
			echo
			echo 'TESTING ABORTED.'
			rm -f $TMP
			exit $?
		fi
		echo "================ END $t OUTPUT ================" >> $TMP
		echo >> $TMP
	fi
done
echo

# Test ssqlsxlat -o.  Note that it suppresses stdout but keeps stderr
# so warnings about directives and line elements it doesn't understand
# aren't suppressed.  We run the first pass's output back through
# ssqlsxlat to deal with comments, whitespace differences, line element
# ordering, boolean value and type canonicalization, and other niggly
# differences we really don't care about.  diff -w isn't enough.
for f in {examples,test}/*.ssqls
do
	echo -n "Testing ssqlsxlat -i $f -o..."
	echo "--- BEGIN ssqlsxlat -i $f -o ERROR OUTPUT ---" >> $TMP
	pass1=/tmp/dtest-ssxgv2-pass1-$bnf
	pass2=/tmp/dtest-ssxgv2-pass2-$bnf
	echo -n "pass 1"
	./exrun ssqlsxlat -i $f -o $pass1 > /dev/null 2>> $TMP

	echo -n ", pass 2"
	./exrun ssqlsxlat -i $pass1 -o $pass2 > /dev/null 2>> $TMP
	echo -n ", diff"
	diff $pass1 $pass2 > /dev/null >> $TMP
	echo "==== END ssqlsxlat -i $f -o ERROR OUTPUT ====" >> $TMP
	echo
done

# Check for any changes
BFILE=bmark.txt
if [ -f $BFILE ]


then
	if diff -u -w $BFILE $TMP
	then


		echo
		echo 'All tests passed.'
	fi
	rm -f $TMP
else
	mv $TMP $BFILE
	chmod -w $BFILE
	echo
	echo 'BENCHMARK FILE REGENERATED.'
	echo
fi
|
>
>
>

<
>
>
>

|
|
<
<
<
<
<
|
|
|
|
|
|
|
|
|
<
<
<
<
<
<
<

>
|
|
|
>

<
<
<
<
<
|
|
|
|
|
|
<
|
<
<
<
<
|
|
|
>
>
>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<
|
<
>
|
|
<
<
<
|
|
|
<
<
<
>
>
|
<
|
>
>
|
<
<
<
<
<
<
<
<
<
<
1
2
3
4
5

6
7
8
9
10
11





12
13
14
15
16
17
18
19
20







21
22
23
24
25
26
27





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
56
57
58
59
60
61
62
63
64
65

66

67
68
69



70
71
72



73
74
75

76
77
78
79










/***********************************************************************
 test/qstream.cpp - Tests insertion of all officially-supported data
	types into a Query stream, plus some that aren't official.  Failure
	is defined as an exception being thrown for any one of these.


 Copyright (c) 2008 by Educational Technology Resources, Inc.
 Others may also hold copyrights on code in this file.  See the
 CREDITS.txt file in the top directory of the distribution for details.

 This file is part of MySQL++.






 MySQL++ is free software; you can redistribute it and/or modify it
 under the terms of the GNU Lesser General Public License as published
 by the Free Software Foundation; either version 2.1 of the License, or
 (at your option) any later version.

 MySQL++ is distributed in the hope that it will be useful, but WITHOUT
 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
 License for more details.








 You should have received a copy of the GNU Lesser General Public
 License along with MySQL++; if not, write to the Free Software
 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
 USA
***********************************************************************/






#include <mysql++.h>

#include <iostream>

using namespace mysqlpp;


int




main()
{
	try {
		// If you're reading this for implicit recommendations of good
		// code style, please ignore the hack-job on the following line.
		mysqlpp::Query q = mysqlpp::Connection().query();

		// Throw everything we can think of at Query's stream interface.
		// Don't do this in real code, either.
		q << 	sql_tinyint(0) << sql_tinyint_unsigned(0) <<
				sql_smallint(0) << sql_smallint_unsigned(0) <<
				sql_mediumint(0) << sql_mediumint_unsigned(0) <<
				sql_int(0) << sql_int_unsigned(0) << long(0) <<
				sql_bigint(0) << sql_bigint_unsigned(0) << longlong(0) <<
				sql_int1(0) << sql_int2(0) << sql_int3(0) <<
				sql_int4(0) << sql_int8(0) << sql_middleint(0) <<
				sql_float(0) << sql_double(0) << sql_decimal(0) <<
				sql_numeric(0) <<
				sql_fixed(0) << sql_float4(0) << sql_float8(0) <<
				sql_bool(false) << sql_boolean(false) << bool(false) <<
				sql_enum() <<
				sql_char() << sql_varchar() << sql_long_varchar() <<
				sql_character_varying() << sql_long() <<
				sql_tinytext() << sql_text() <<
				sql_mediumtext() << sql_longtext() <<
				sql_blob() << sql_tinyblob() << sql_mediumblob() <<
				sql_longblob() << sql_long_varbinary() <<
				sql_date() << sql_time() << sql_datetime() <<
				sql_timestamp() <<
				sql_set();
		std::cout << q << std::endl;

		return 0;

	}
	catch (const mysqlpp::TypeLookupFailed& e) {
		std::cerr << "Query stream insert failed: " << e.what() <<



				std::endl;
		return 1;
	}



	catch (const std::exception& e) {
		std::cerr << "Unexpected exception: " << e.what() <<
				std::endl;

		return 1;
	}
}











Changes to examples/cgi_jpeg.cpp.

1
2
3
4
5
6
7
8
9
10
11
12
/***********************************************************************
 cgi_jpeg.cpp - Example code showing how to fetch JPEG data from a BLOB
 	column and send it back to a browser that requested it by ID.
	
	Use load_jpeg.cpp to load JPEG files into the database we query.

 Copyright (c) 1998 by Kevin Atkinson, (c) 1999-2001 by MySQL AB, and
 (c) 2004-2009 by Educational Technology Resources, Inc.  Others may
 also hold copyrights on code in this file.  See the CREDITS.txt file
 in the top directory of the distribution for details.

 This file is part of MySQL++.

<
|
|
<







1

2
3

4
5
6
7
8
9
10
/***********************************************************************

 fieldinf.cpp - Shows how to request information about the fields in a
	table, such as their SQL and C++-equivalent types.


 Copyright (c) 1998 by Kevin Atkinson, (c) 1999-2001 by MySQL AB, and
 (c) 2004-2009 by Educational Technology Resources, Inc.  Others may
 also hold copyrights on code in this file.  See the CREDITS.txt file
 in the top directory of the distribution for details.

 This file is part of MySQL++.
24
25
26
27
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
56
57

58
59


60
61
62
63
64
65
66

67
68
69
70
71
72

73
74
75











76
77
78
79
80
81
82
83
84
85
86
87
88

89
90

91
92
93
94
95
96



97
98
99

100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
 You should have received a copy of the GNU Lesser General Public
 License along with MySQL++; if not, write to the Free Software
 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
 USA
***********************************************************************/

#include "cmdline.h"
#include "images.h"



#define CRLF			"\r\n"

#define CRLF2			"\r\n\r\n"

int
main(int argc, char* argv[])
{
	// Get database access parameters from command line if present, else
	// use hard-coded values for true CGI case.
	mysqlpp::examples::CommandLine cmdline(argc, argv, "root",
			"nunyabinness");
	if (!cmdline) {
		return 1;
	}

	// Parse CGI query string environment variable to get image ID
	unsigned int img_id = 0;
	char* cgi_query = getenv("QUERY_STRING");
	if (cgi_query) {
		if ((strlen(cgi_query) < 4) || memcmp(cgi_query, "id=", 3)) {
			std::cout << "Content-type: text/plain" << std::endl << std::endl;
			std::cout << "ERROR: Bad query string" << std::endl;
			return 1;
		}
		else {
			img_id = atoi(cgi_query + 3);

		}
	}


	else {
		std::cerr << "Put this program into a web server's cgi-bin "
				"directory, then" << std::endl;
		std::cerr << "invoke it with a URL like this:" << std::endl;
		std::cerr << std::endl;
		std::cerr << "    http://server.name.com/cgi-bin/cgi_jpeg?id=2" <<
				std::endl;

		std::cerr << std::endl;
		std::cerr << "This will retrieve the image with ID 2." << std::endl;
		std::cerr << std::endl;
		std::cerr << "You will probably have to change some of the #defines "
				"at the top of" << std::endl;
		std::cerr << "examples/cgi_jpeg.cpp to allow the lookup to work." <<

				std::endl;
		return 1;
	}












	// Retrieve image from DB by ID
	try {
		mysqlpp::Connection con(mysqlpp::examples::db_name,
				cmdline.server(), cmdline.user(), cmdline.pass());
		mysqlpp::Query query = con.query();
		query << "SELECT * FROM images WHERE id = " << img_id;
		mysqlpp::StoreQueryResult res = query.store();
		if (res && res.num_rows()) {
			images img = res[0];
			if (img.data.is_null) {
				std::cout << "Content-type: text/plain" << CRLF2;
				std::cout << "No image content!" << CRLF;

			}
			else {

				std::cout << "X-Image-Id: " << img_id << CRLF; // for debugging
				std::cout << "Content-type: image/jpeg" << CRLF;
				std::cout << "Content-length: " <<
						img.data.data.length() << CRLF2;
				std::cout << img.data;
			}



		}
		else {
			std::cout << "Content-type: text/plain" << CRLF2;

			std::cout << "ERROR: No image with ID " << img_id << CRLF;
		}
	}
	catch (const mysqlpp::BadQuery& er) {
		// Handle any query errors
		std::cout << "Content-type: text/plain" << CRLF2;
		std::cout << "QUERY ERROR: " << er.what() << CRLF;
		return 1;
	}
	catch (const mysqlpp::Exception& er) {
		// Catch-all for any other MySQL++ exceptions
		std::cout << "Content-type: text/plain" << CRLF2;
		std::cout << "GENERAL ERROR: " << er.what() << CRLF;
		return 1;
	}

	return 0;
}







|

>
>
|
>
|


|

|
<
|
<




|
|
|
|
<
<
<
<
|
|
|
>
|
<
>
>
|
<
|
|
|
<
|
>
|
<
<
<
<
<
>
|
<
|
>
>
>
>
>
>
>
>
>
>
>
|
<
<
<
<
<
|
|
<
|
|
<
|
>
|
|
>
|
|
|
<
|
|
>
>
>


|
>
|




<
|
|



<
|
|




22
23
24
25
26
27
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
56
57

58
59
60

61
62
63





64
65

66
67
68
69
70
71
72
73
74
75
76
77
78





79
80

81
82

83
84
85
86
87
88
89
90

91
92
93
94
95
96
97
98
99
100
101
102
103
104

105
106
107
108
109

110
111
112
113
114
115
 You should have received a copy of the GNU Lesser General Public
 License along with MySQL++; if not, write to the Free Software
 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
 USA
***********************************************************************/

#include "cmdline.h"
#include "printdata.h"

#include <iostream>
#include <iomanip>

using namespace std;


int
main(int argc, char *argv[])
{
	// Get database access parameters from command line

	mysqlpp::examples::CommandLine cmdline(argc, argv);

	if (!cmdline) {
		return 1;
	}

	try {
		// Establish the connection to the database server.
		mysqlpp::Connection con(mysqlpp::examples::db_name,
				cmdline.server(), cmdline.user(), cmdline.pass());





		// Get contents of main example table
		mysqlpp::Query query = con.query("select * from stock");
		mysqlpp::StoreQueryResult res = query.store();


		// Show info about each field in that table
		char widths[] = { 12, 22, 46 };
		cout.setf(ios::left);

		cout << setw(widths[0]) << "Field" <<
				setw(widths[1]) << "SQL Type" <<
				setw(widths[2]) << "Equivalent C++ Type" <<

				endl;
		for (size_t i = 0; i < sizeof(widths) / sizeof(widths[0]); ++i) {
			cout << string(widths[i] - 1, '=') << ' ';





		}
		cout << endl;

		
		for (size_t i = 0; i < res.field_names()->size(); i++) {
			// Suppress C++ type name outputs when run under dtest,
			// as they're system-specific.
			const char* cname = res.field_type(int(i)).name();
			mysqlpp::FieldTypes::value_type ft = res.field_type(int(i));
			ostringstream os;
			os << ft.sql_name() << " (" << ft.id() << ')';
			cout << setw(widths[0]) << res.field_name(int(i)).c_str() <<
					setw(widths[1]) << os.str() <<
					setw(widths[2]) << cname <<
					endl;
		}





		cout << endl;


		// Simple type check
		if (res.field_type(0) == typeid(string)) {

			cout << "SQL type of 'item' field most closely resembles "
					"the C++ string type." << endl;
		}

		// Tricky type check: the 'if' path shouldn't happen because the
		// description field has the NULL attribute.  We need to dig a
		// little deeper if we want to ignore this in our type checks.
		if (res.field_type(5) == typeid(string)) {

			cout << "Should not happen! Type check failure." << endl;
		}
		else if (res.field_type(5) == typeid(mysqlpp::sql_blob_null)) {
			cout << "SQL type of 'description' field resembles "
					"a nullable variant of the C++ string type." << endl;
		}
		else {
			cout << "Weird: fifth field's type is now " <<
					res.field_type(5).name() << endl;
			cout << "Did something recently change in resetdb?" << endl;
		}
	}
	catch (const mysqlpp::BadQuery& er) {
		// Handle any query errors

		cerr << "Query error: " << er.what() << endl;
		return -1;
	}
	catch (const mysqlpp::Exception& er) {
		// Catch-all for any other MySQL++ exceptions

		cerr << "Error: " << er.what() << endl;
		return -1;
	}

	return 0;
}

Changes to examples/cpool.cpp.

1
2
3
4
5

6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
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
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
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
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
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209

210
211
212
213




214
215
216
217
218
219
220

221
222
223

224
225
226

227
228
229
230
231
232
233

234
235
236


237
238


239
240
241
242
243
244
245
246

247
248
249
/***********************************************************************
 cpool.cpp - ConnectionPool example.  Works with both Windows native
	threads and POSIX threads.  Shows how to create and use a concrete
	ConnectionPool derivative.


 Copyright (c) 2008-2010 by Educational Technology Resources, Inc.
 Others may also hold copyrights on code in this file.  See the
 CREDITS.txt file in the top directory of the distribution for details.

 This file is part of MySQL++.

 MySQL++ is free software; you can redistribute it and/or modify it
 under the terms of the GNU Lesser General Public License as published
 by the Free Software Foundation; either version 2.1 of the License, or
 (at your option) any later version.

 MySQL++ is distributed in the hope that it will be useful, but WITHOUT
 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
 License for more details.

 You should have received a copy of the GNU Lesser General Public
 License along with MySQL++; if not, write to the Free Software
 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
 USA
***********************************************************************/

#include "cmdline.h"

#include "threads.h"

#include <iostream>


using namespace std;


#if defined(HAVE_THREADS)
// Define a concrete ConnectionPool derivative.  Takes connection
// parameters as inputs to its ctor, which it uses to create the
// connections we're called upon to make.  Note that we also declare
// a global pointer to an object of this type, which we create soon
// after startup; this should be a common usage pattern, as what use
// are multiple pools?
class SimpleConnectionPool : public mysqlpp::ConnectionPool
{
public:
	// The object's only constructor
	SimpleConnectionPool(mysqlpp::examples::CommandLine& cl) :
	conns_in_use_(0),
	db_(mysqlpp::examples::db_name),
	server_(cl.server()),
	user_(cl.user()),
	password_(cl.pass())
	{
	}

	// The destructor.  We _must_ call ConnectionPool::clear() here,
	// because our superclass can't do it for us.
	~SimpleConnectionPool()
	{
		clear();
	}

	// Do a simple form of in-use connection limiting: wait to return
	// a connection until there are a reasonably low number in use
	// already.  Can't do this in create() because we're interested in
	// connections actually in use, not those created.  Also note that
	// we keep our own count; ConnectionPool::size() isn't the same!
	mysqlpp::Connection* grab()
	{
		while (conns_in_use_ > 8) {
			cout.put('R'); cout.flush(); // indicate waiting for release
			sleep(1);
		}

		++conns_in_use_;
		return mysqlpp::ConnectionPool::grab();
	}

	// Other half of in-use conn count limit
	void release(const mysqlpp::Connection* pc)
	{
		mysqlpp::ConnectionPool::release(pc);
		--conns_in_use_;
	}

protected:
	// Superclass overrides
	mysqlpp::Connection* create()
	{
		// Create connection using the parameters we were passed upon
		// creation.  This could be something much more complex, but for
		// the purposes of the example, this suffices.
		cout.put('C'); cout.flush(); // indicate connection creation
		return new mysqlpp::Connection(
				db_.empty() ? 0 : db_.c_str(),
				server_.empty() ? 0 : server_.c_str(),
				user_.empty() ? 0 : user_.c_str(),
				password_.empty() ? "" : password_.c_str());
	}

	void destroy(mysqlpp::Connection* cp)
	{
		// Our superclass can't know how we created the Connection, so
		// it delegates destruction to us, to be safe.
		cout.put('D'); cout.flush(); // indicate connection destruction
		delete cp;
	}

	unsigned int max_idle_time()
	{
		// Set our idle time at an example-friendly 3 seconds.  A real
		// pool would return some fraction of the server's connection
		// idle timeout instead.
		return 3;
	}

private:
	// Number of connections currently in use
	unsigned int conns_in_use_;

	// Our connection parameters
	std::string db_, server_, user_, password_;
};
SimpleConnectionPool* poolptr = 0;


static thread_return_t CALLBACK_SPECIFIER
worker_thread(thread_arg_t running_flag)
{
	// Ask the underlying C API to allocate any per-thread resources it
	// needs, in case it hasn't happened already.  In this particular
	// program, it's almost guaranteed that the safe_grab() call below
	// will create a new connection the first time through, and thus
	// allocate these resources implicitly, but there's a nonzero chance
	// that this won't happen.  Anyway, this is an example program,
	// meant to show good style, so we take the high road and ensure the
	// resources are allocated before we do any queries.
	mysqlpp::Connection::thread_start();
	cout.put('S'); cout.flush(); // indicate thread started

	// Pull data from the sample table a bunch of times, releasing the
	// connection we use each time.
	for (size_t i = 0; i < 6; ++i) {
		// Go get a free connection from the pool, or create a new one
		// if there are no free conns yet.  Uses safe_grab() to get a
		// connection from the pool that will be automatically returned
		// to the pool when this loop iteration finishes.
		mysqlpp::ScopedConnection cp(*poolptr, true);
		if (!cp) {
			cerr << "Failed to get a connection from the pool!" << endl;
			break;
		}

		// Pull a copy of the sample stock table and print a dot for
		// each row in the result set.
		mysqlpp::Query query(cp->query("select * from stock"));
		mysqlpp::StoreQueryResult res = query.store();
		for (size_t j = 0; j < res.num_rows(); ++j) {
			cout.put('.');
		}

		// Delay 1-4 seconds before doing it again.  Because this can
		// delay longer than the idle timeout, we'll occasionally force
		// the creation of a new connection on the next loop.
		sleep(rand() % 4 + 1);	
	}

	// Tell main() that this thread is no longer running
	*reinterpret_cast<bool*>(running_flag) = false;
	cout.put('E'); cout.flush(); // indicate thread ended
	
	// Release the per-thread resources before we exit
	mysqlpp::Connection::thread_end();

	return 0;
}
#endif


int
main(int argc, char *argv[])
{
#if defined(HAVE_THREADS)
	// Get database access parameters from command line
	mysqlpp::examples::CommandLine cmdline(argc, argv);
	if (!cmdline) {
		return 1;
	}

	// Create the pool and grab a connection.  We do it partly to test
	// that the parameters are good before we start doing real work, and
	// partly because we need a Connection object to call thread_aware()
	// on to check that it's okay to start doing that real work.  This
	// latter check should never fail on Windows, but will fail on most
	// other systems unless you take positive steps to build with thread
	// awareness turned on.  See README-*.txt for your platform.
	poolptr = new SimpleConnectionPool(cmdline);
	try {
		mysqlpp::ScopedConnection cp(*poolptr, true);
		if (!cp->thread_aware()) {
			cerr << "MySQL++ wasn't built with thread awareness!  " <<
					argv[0] << " can't run without it." << endl;
			return 1;
		}
	}
	catch (mysqlpp::Exception& e) {
		cerr << "Failed to set up initial pooled connection: " <<
				e.what() << endl;
		return 1;

	}

	// Setup complete.  Now let's spin some threads...
	cout << endl << "Pool created and working correctly.  Now to do "




			"some real work..." << endl;
	srand((unsigned int)time(0));
	bool running[] = {
			true, true, true, true, true, true, true,
			true, true, true, true, true, true, true };
	const size_t num_threads = sizeof(running) / sizeof(running[0]);
	size_t i;

	for (i = 0; i < num_threads; ++i) {
		if (int err = create_thread(worker_thread, running + i)) {
			cerr << "Failed to create thread " << i <<

					": error code " << err << endl;
			return 1;
		}

	}

	// Test the 'running' flags every second until we find that they're
	// all turned off, indicating that all threads are stopped.
	cout.put('W'); cout.flush(); // indicate waiting for completion
	do {
		sleep(1);

		i = 0;
		while (i < num_threads && !running[i]) ++i;
	}


	while (i < num_threads);
	cout << endl << "All threads stopped!" << endl;



	// Shut it all down...
	delete poolptr;
	cout << endl;
#else
	(void)argc;		// warning squisher
	cout << argv[0] << " requires that threads be enabled!" << endl;
#endif


	return 0;
}

|
|
|
|
>
|
|
|




















>
|


>


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




<






<
<
<
<
<
<
<
<
|
|
<
<
<
<
<
<
|
<
<
<
>
|
|
<
<
>
>
>
>
|
<
|
<
|
|
|
>
|
<
|
>
|
<
|
>
|
|
<
|
<
<
|
>
|
<

>
>
|
|
>
>
|
<
<
|
|
<
|
|
>



1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
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
56
57

58

59
60
61
62
63

64
65
66

67
68
69
70

71


72
73
74

75
76
77
78
79
80
81
82


83
84

85
86
87
88
89
90
/***********************************************************************
 ssqls1.cpp - Example that produces the same results as simple1, but it
	uses a Specialized SQL Structure to store the results instead of a
	MySQL++ Result object.
 
 Copyright (c) 1998 by Kevin Atkinson, (c) 1999-2001 by MySQL AB, and
 (c) 2004-2009 by Educational Technology Resources, Inc.  Others may
 also hold copyrights on code in this file.  See the CREDITS.txt file
 in the top directory of the distribution for details.

 This file is part of MySQL++.

 MySQL++ is free software; you can redistribute it and/or modify it
 under the terms of the GNU Lesser General Public License as published
 by the Free Software Foundation; either version 2.1 of the License, or
 (at your option) any later version.

 MySQL++ is distributed in the hope that it will be useful, but WITHOUT
 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
 License for more details.

 You should have received a copy of the GNU Lesser General Public
 License along with MySQL++; if not, write to the Free Software
 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
 USA
***********************************************************************/

#include "cmdline.h"
#include "printdata.h"
#include "stock.h"

#include <iostream>
#include <vector>

using namespace std;


















































































































































int
main(int argc, char *argv[])
{

	// Get database access parameters from command line
	mysqlpp::examples::CommandLine cmdline(argc, argv);
	if (!cmdline) {
		return 1;
	}









	try {						
		// Establish the connection to the database server.






		mysqlpp::Connection con(mysqlpp::examples::db_name,



				cmdline.server(), cmdline.user(), cmdline.pass());

		// Retrieve a subset of the stock table's columns, and store


		// the data in a vector of 'stock' SSQLS structures.  See the
		// user manual for the consequences arising from this quiet
		// ability to store a subset of the table in the stock SSQLS.
		mysqlpp::Query query = con.query("select item,description from stock");
		vector<stock> res;

		query.storein(res);


		// Display the items
		cout << "We have:" << endl;
		vector<stock>::iterator it;
		for (it = res.begin(); it != res.end(); ++it) {

			cout << '\t' << it->item;
			if (it->description != mysqlpp::null) {
				cout << " (" << it->description << ")";

			}
			cout << endl;
		}
	}

	catch (const mysqlpp::BadQuery& er) {


		// Handle any query errors
		cerr << "Query error: " << er.what() << endl;
		return -1;

	}
	catch (const mysqlpp::BadConversion& er) {
		// Handle bad conversions; e.g. type mismatch populating 'stock'
		cerr << "Conversion error: " << er.what() << endl <<
				"\tretrieved data size: " << er.retrieved <<
				", actual size: " << er.actual_size << endl;
		return -1;
	}


	catch (const mysqlpp::Exception& er) {
		// Catch-all for any other MySQL++ exceptions

		cerr << "Error: " << er.what() << endl;
		return -1;
	}

	return 0;
}

Changes to examples/dbinfo.cpp.

1
2

3

4
5
6
7
8
9
10
/***********************************************************************
 dbinfo.cpp - Example showing how to request information about the

	database schema, such as table names, column types, etc.


 Copyright (c) 1998 by Kevin Atkinson, (c) 1999-2001 by MySQL AB, and
 (c) 2004-2009 by Educational Technology Resources, Inc.  Others may
 also hold copyrights on code in this file.  See the CREDITS.txt file
 in the top directory of the distribution for details.

 This file is part of MySQL++.

|
>
|
>







1
2
3
4
5
6
7
8
9
10
11
12
/***********************************************************************
 cgi_jpeg.cpp - Example code showing how to fetch JPEG data from a BLOB
 	column and send it back to a browser that requested it by ID.
	
	Use load_jpeg.cpp to load JPEG files into the database we query.

 Copyright (c) 1998 by Kevin Atkinson, (c) 1999-2001 by MySQL AB, and
 (c) 2004-2009 by Educational Technology Resources, Inc.  Others may
 also hold copyrights on code in this file.  See the CREDITS.txt file
 in the top directory of the distribution for details.

 This file is part of MySQL++.
22
23
24
25
26
27
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
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
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
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
191
192
 You should have received a copy of the GNU Lesser General Public
 License along with MySQL++; if not, write to the Free Software
 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
 USA
***********************************************************************/

#include "cmdline.h"
#include "printdata.h"

#include <mysql++.h>

#include <iomanip>
#include <iostream>
#include <string>
#include <vector>

using namespace std;


// Insert a bar into the stream with the given query string centered
static void
separator(ostream& os, string qstr)
{
	string sep("========================================"
			"========================================");
	if (qstr.size()) {
		string::size_type start = (sep.size() - qstr.size()) / 2;
		sep.replace(start - 1, 1, 1, ' ');
		sep.replace(start, qstr.size(), qstr);
		sep.replace(start + qstr.size(), 1, 1, ' ');
		os << "\n\n";
	}
	os << sep << endl;
}


// Print out the MySQL server version
static void
show_mysql_version(mysqlpp::Connection& con)
{
	separator(cout, "");
    cout << "MySQL version: " << con.client_version();
}


// Print out the names of all the databases managed by the server
static void
show_databases(mysqlpp::Connection& con)
{
	mysqlpp::Query query = con.query("show databases");
	separator(cout, query.str());
	mysqlpp::StoreQueryResult res = query.store();

	cout << "Databases found: " << res.size();
	cout.setf(ios::left);
	mysqlpp::StoreQueryResult::iterator rit;
	for (rit = res.begin(); rit != res.end(); ++rit) {
		cout << "\n\t" << (*rit)[0];
	}
}


// Print information about each of the tables we found
static void
show_table_info(mysqlpp::Connection& con, const vector<string>& tables)
{
	vector<string>::const_iterator it;
	for (it = tables.begin(); it != tables.end(); ++it) {
		mysqlpp::Query query = con.query();
		query << "describe " << *it;
		separator(cout, query.str());
		mysqlpp::StoreQueryResult res = query.store();

		size_t columns = res.num_fields();
		vector<size_t> widths;
		for (size_t i = 0; i < columns; ++i) {
			string s = res.field_name(int(i));
			if (s.compare("field") == 0) {
				widths.push_back(22);
			}
			else if (s.compare("type") == 0) {
				widths.push_back(20);
			}
			else if (s.compare("null") == 0) {
				widths.push_back(4);
			}
			else if (s.compare("key") == 0) {
				widths.push_back(3);
			}
			else if (s.compare("extra") == 0) {
				widths.push_back(0);
			}
			else {
				widths.push_back(15);
			}

			if (widths[i]) {
				cout << '|' << setw(widths[i]) << 
						res.field_name(int(i)) << '|';
			}
		}
		cout << endl;

		mysqlpp::StoreQueryResult::iterator rit;
		for (rit = res.begin(); rit != res.end(); ++rit) {
			for (unsigned int i = 0; i < columns; ++i) {
				if (widths[i]) {
					cout << ' ' << setw(widths[i]) <<
							(*rit)[i].c_str() << ' ';
				}
			}
			cout << endl;
		}
	}
}


// Print out the names of all tables in the sample database, and
// return the list of tables.
static void
show_tables(mysqlpp::Connection& con)
{
	mysqlpp::Query query = con.query("show tables");
	separator(cout, query.str());
	mysqlpp::StoreQueryResult res = query.store();

	cout << "Tables found: " << res.size();
	cout.setf(ios::left);
	vector<string> tables;
	mysqlpp::StoreQueryResult::iterator rit;
	for (rit = res.begin(); rit != res.end(); ++rit) {
		string tbl((*rit)[0]);
		cout << "\n\t" << tbl;
		tables.push_back(tbl);
	}

	show_table_info(con, tables);
}


// Call all the above functions in sequence
int
main(int argc, char* argv[])
{
	// Get database access parameters from command line

	mysqlpp::examples::CommandLine cmdline(argc, argv);

	if (!cmdline) {
		return 1;
	}
































	try {
		// Connect to server, then dump a bunch of stuff we find on it
		mysqlpp::Connection con(mysqlpp::examples::db_name,
				cmdline.server(), cmdline.user(), cmdline.pass());
		show_mysql_version(con);




		show_databases(con);

		show_tables(con);













	}
	catch (const mysqlpp::BadQuery& er) {
		// Handle any query errors

		cerr << "Query error: " << er.what() << endl;
		return -1;
	}
	catch (const mysqlpp::Exception& er) {
		// Catch-all for any other MySQL++ exceptions

		cerr << "Error: " << er.what() << endl;
		return -1;
	}

	return 0;
}







|

<
|
<
<
<
<
|
<

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



|
>
|
>




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

<


|
>
>
>
>
|
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>



>
|
|



>
|
|




24
25
26
27
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
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78

79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
 You should have received a copy of the GNU Lesser General Public
 License along with MySQL++; if not, write to the Free Software
 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
 USA
***********************************************************************/

#include "cmdline.h"
#include "images.h"


#define CRLF			"\r\n"




#define CRLF2			"\r\n\r\n"





























































































































int
main(int argc, char* argv[])
{
	// Get database access parameters from command line if present, else
	// use hard-coded values for true CGI case.
	mysqlpp::examples::CommandLine cmdline(argc, argv, "root",
			"nunyabinness");
	if (!cmdline) {
		return 1;
	}

	// Parse CGI query string environment variable to get image ID
	unsigned int img_id = 0;
	char* cgi_query = getenv("QUERY_STRING");
	if (cgi_query) {
		if ((strlen(cgi_query) < 4) || memcmp(cgi_query, "id=", 3)) {
			std::cout << "Content-type: text/plain" << std::endl << std::endl;
			std::cout << "ERROR: Bad query string" << std::endl;
			return 1;
		}
		else {
			img_id = atoi(cgi_query + 3);
		}
	}
	else {
		std::cerr << "Put this program into a web server's cgi-bin "
				"directory, then" << std::endl;
		std::cerr << "invoke it with a URL like this:" << std::endl;
		std::cerr << std::endl;
		std::cerr << "    http://server.name.com/cgi-bin/cgi_jpeg?id=2" <<
				std::endl;
		std::cerr << std::endl;
		std::cerr << "This will retrieve the image with ID 2." << std::endl;
		std::cerr << std::endl;
		std::cerr << "You will probably have to change some of the #defines "
				"at the top of" << std::endl;
		std::cerr << "examples/cgi_jpeg.cpp to allow the lookup to work." <<
				std::endl;
		return 1;
	}

	// Retrieve image from DB by ID
	try {

		mysqlpp::Connection con(mysqlpp::examples::db_name,
				cmdline.server(), cmdline.user(), cmdline.pass());
		mysqlpp::Query query = con.query();
		query << "SELECT * FROM images WHERE id = " << img_id;
		mysqlpp::StoreQueryResult res = query.store();
		if (res && res.num_rows()) {
			images img = res[0];
			if (img.data.is_null) {
				std::cout << "Content-type: text/plain" << CRLF2;
				std::cout << "No image content!" << CRLF;
			}
			else {
				std::cout << "X-Image-Id: " << img_id << CRLF; // for debugging
				std::cout << "Content-type: image/jpeg" << CRLF;
				std::cout << "Content-length: " <<
						img.data.data.length() << CRLF2;
				std::cout << img.data;
			}
		}
		else {
			std::cout << "Content-type: text/plain" << CRLF2;
			std::cout << "ERROR: No image with ID " << img_id << CRLF;
		}
	}
	catch (const mysqlpp::BadQuery& er) {
		// Handle any query errors
		std::cout << "Content-type: text/plain" << CRLF2;
		std::cout << "QUERY ERROR: " << er.what() << CRLF;
		return 1;
	}
	catch (const mysqlpp::Exception& er) {
		// Catch-all for any other MySQL++ exceptions
		std::cout << "Content-type: text/plain" << CRLF2;
		std::cout << "GENERAL ERROR: " << er.what() << CRLF;
		return 1;
	}

	return 0;
}

Changes to examples/deadlock.cpp.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
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
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80

81
82
83
84
85
86
87
88
89



90
91
92
93
94
95
96
97

98
99
100
101
102
103
104

105

106
107
108


109
110
111

112
113
114
115
116
117
/***********************************************************************
 deadlock.cpp - Demonstrates how MySQL's deadlock detection interacts
	with MySQL++'s Transaction class an exception handling mechanism.
	Run one copy of this program with the -m1 command line switch, then
	while it's waiting for you to press Enter, run another copy with -m2
	instead.

 Copyright (c) 2007 by Jim Wallace and (c) 2007-2009 by Educational
 Technology Resources, Inc.  Others may also hold copyrights on code
 in this file.  See the CREDITS.txt file in the top directory of the
 distribution for details.

 This file is part of MySQL++.

 MySQL++ is free software; you can redistribute it and/or modify it
 under the terms of the GNU Lesser General Public License as published
 by the Free Software Foundation; either version 2.1 of the License, or
 (at your option) any later version.

 MySQL++ is distributed in the hope that it will be useful, but WITHOUT
 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
 License for more details.

 You should have received a copy of the GNU Lesser General Public
 License along with MySQL++; if not, write to the Free Software
 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
 USA
***********************************************************************/

#include "cmdline.h"

#include <mysql++.h>
#include <mysqld_error.h>

#include <iostream>


using namespace std;

// Bring in global holding the value given to the -m switch
extern int run_mode;


int
main(int argc, char *argv[])
{
	// Get database access parameters from command line
	mysqlpp::examples::CommandLine cmdline(argc, argv);
	if (!cmdline) {
		return 1;
	}

	// Check that the mode parameter was also given and it makes sense
	const int run_mode = cmdline.run_mode();
	if ((run_mode != 1) && (run_mode != 2)) {
		cerr << argv[0] << " must be run with -m1 or -m2 as one of "
				"its command-line arguments." << endl;
		return 1;
	}

	mysqlpp::Connection con;
	try {
		// Establish the connection to the database server
		mysqlpp::Connection con(mysqlpp::examples::db_name,
				cmdline.server(), cmdline.user(), cmdline.pass());

		// Start a transaction set.  Transactions create mutex locks on
		// modified rows, so if two programs both touch the same pair of
		// rows but in opposite orders at the wrong time, one of the two
		// programs will deadlock.  The MySQL server knows how to detect
		// this situation, and its error return causes MySQL++ to throw
		// a BadQuery exception.  The point of this example is that if
		// you want to detect this problem, you would check the value of
		// BadQuery::errnum(), not Connection::errnum(), because the
		// transaction rollback process executes a query which succeeds,
		// setting the MySQL C API's "last error number" value to 0.
		// The exception object carries its own copy of the error number
		// at the point the exception was thrown for this very reason.
		mysqlpp::Query query = con.query();
		mysqlpp::Transaction trans(con);


		// Build and run the queries, with the order depending on the -m
		// flag, so that a second copy of the program will deadlock if
		// run while the first is waiting for Enter.
		char dummy[100];
		for (int i = 0; i < 2; ++i) {
			int lock = run_mode + (run_mode == 1 ? i : -i);
			cout << "Trying lock " << lock << "..." << endl;




			query << "select * from deadlock_test" << lock << 
					" where x = " << lock << " for update";
			query.store();

			cout << "Acquired lock " << lock << ".  Press Enter to ";
			cout << (i == 0 ? "try next lock" : "exit");
			cout << ": " << flush;
			cin.getline(dummy, sizeof(dummy));

		}
	}
	catch (mysqlpp::BadQuery e) {
		if (e.errnum() == ER_LOCK_DEADLOCK) {
			cerr << "Transaction deadlock detected!" << endl;
			cerr << "Connection::errnum = " << con.errnum() <<
					", BadQuery::errnum = " << e.errnum() << endl;

		}

		else {
			cerr << "Unexpected query error: " << e.what() << endl;
		}


		return 1;
	}
	catch (mysqlpp::Exception e) {

		cerr << "General error: " << e.what() << endl;		
		return 1;
	}

	return 0;
}

|
|
<
<
<

|
|
|
|




















<
|
|


>


<
<
<
<










<
<
<
<
<
<
<
<
<

|



|
|
|
|
|
|
|
<
|
<
<
<

<
>

|
<
<
<
<
<
|

>
>
>
<
<
<

<
<
|
<
>
|
<
|
|
<
<
|
>
|
>
|
|
<
>
>
|

|
>
|
|




1
2
3



4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
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
56
57

58



59

60
61
62





63
64
65
66
67



68


69

70
71

72
73


74
75
76
77
78
79

80
81
82
83
84
85
86
87
88
89
90
91
/***********************************************************************
 ssqls2.cpp - Example showing how to insert a row using the Specialized
	SQL Structures feature of MySQL++.




 Copyright (c) 1998 by Kevin Atkinson, (c) 1999-2001 by MySQL AB, and
 (c) 2004-2009 by Educational Technology Resources, Inc.  Others may
 also hold copyrights on code in this file.  See the CREDITS.txt file
 in the top directory of the distribution for details.

 This file is part of MySQL++.

 MySQL++ is free software; you can redistribute it and/or modify it
 under the terms of the GNU Lesser General Public License as published
 by the Free Software Foundation; either version 2.1 of the License, or
 (at your option) any later version.

 MySQL++ is distributed in the hope that it will be useful, but WITHOUT
 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
 License for more details.

 You should have received a copy of the GNU Lesser General Public
 License along with MySQL++; if not, write to the Free Software
 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
 USA
***********************************************************************/

#include "cmdline.h"

#include "printdata.h"
#include "stock.h"

#include <iostream>
#include <limits>

using namespace std;





int
main(int argc, char *argv[])
{
	// Get database access parameters from command line
	mysqlpp::examples::CommandLine cmdline(argc, argv);
	if (!cmdline) {
		return 1;
	}










	try {
		// Establish the connection to the database server.
		mysqlpp::Connection con(mysqlpp::examples::db_name,
				cmdline.server(), cmdline.user(), cmdline.pass());

		// Create and populate a stock object.  We could also have used
		// the set() member, which takes the same parameters as this
		// constructor.
		stock row("Hot Dogs", 100, 1.5,
				numeric_limits<double>::infinity(),	// "priceless," ha!
				mysqlpp::sql_date("1998-09-25"), mysqlpp::null);


		// Form the query to insert the row into the stock table.



		mysqlpp::Query query = con.query();

		query.insert(row);

		// Show the query about to be executed.





		cout << "Query: " << query << endl;

		// Execute the query.  We use execute() because INSERT doesn't
		// return a result set.
		query.execute();






		// Retrieve and print out the new table contents.

		print_stock_table(query);
	}

	catch (const mysqlpp::BadQuery& er) {
		// Handle any query errors


		cerr << "Query error: " << er.what() << endl;
		return -1;
	}
	catch (const mysqlpp::BadConversion& er) {	
		// Handle bad conversions
		cerr << "Conversion error: " << er.what() << endl <<

				"\tretrieved data size: " << er.retrieved <<
				", actual size: " << er.actual_size << endl;
		return -1;
	}
	catch (const mysqlpp::Exception& er) {
		// Catch-all for any other MySQL++ exceptions
		cerr << "Error: " << er.what() << endl;
		return -1;
	}

	return 0;
}

Changes to examples/fieldinf.cpp.

1
2
3
4
5
6
7
8
9
10
/***********************************************************************
 fieldinf.cpp - Shows how to request information about the fields in a
	table, such as their SQL and C++-equivalent types.

 Copyright (c) 1998 by Kevin Atkinson, (c) 1999-2001 by MySQL AB, and
 (c) 2004-2009 by Educational Technology Resources, Inc.  Others may
 also hold copyrights on code in this file.  See the CREDITS.txt file
 in the top directory of the distribution for details.

 This file is part of MySQL++.

|
|







1
2
3
4
5
6
7
8
9
10
/***********************************************************************
 ssqls3.cpp - Example showing how to update an SQL row using the
	Specialized SQL Structures feature of MySQL++.

 Copyright (c) 1998 by Kevin Atkinson, (c) 1999-2001 by MySQL AB, and
 (c) 2004-2009 by Educational Technology Resources, Inc.  Others may
 also hold copyrights on code in this file.  See the CREDITS.txt file
 in the top directory of the distribution for details.

 This file is part of MySQL++.
23
24
25
26
27
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
56
57
58
59
60
61
62
63
64
65
66
67
68
69




70
71
72
73
74
75
76
77
78


79
80
81
82
83
84

85
86
87
88
89
90
91
92
93

94
95
96

97
98
99
100

101


102
103
104
105
106







107
108
109
110
111
112
113
114
115
 License along with MySQL++; if not, write to the Free Software
 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
 USA
***********************************************************************/

#include "cmdline.h"
#include "printdata.h"


#include <iostream>
#include <iomanip>

using namespace std;


int
main(int argc, char *argv[])
{
	// Get database access parameters from command line
	mysqlpp::examples::CommandLine cmdline(argc, argv);
	if (!cmdline) {
		return 1;
	}

	try {
		// Establish the connection to the database server.
		mysqlpp::Connection con(mysqlpp::examples::db_name,
				cmdline.server(), cmdline.user(), cmdline.pass());

		// Get contents of main example table

		mysqlpp::Query query = con.query("select * from stock");
		mysqlpp::StoreQueryResult res = query.store();

		// Show info about each field in that table
		char widths[] = { 12, 22, 46 };
		cout.setf(ios::left);
		cout << setw(widths[0]) << "Field" <<
				setw(widths[1]) << "SQL Type" <<
				setw(widths[2]) << "Equivalent C++ Type" <<
				endl;
		for (size_t i = 0; i < sizeof(widths) / sizeof(widths[0]); ++i) {
			cout << string(widths[i] - 1, '=') << ' ';
		}
		cout << endl;
		
		for (size_t i = 0; i < res.field_names()->size(); i++) {
			// Suppress C++ type name outputs when run under dtest,
			// as they're system-specific.




			const char* cname = res.field_type(int(i)).name();
			mysqlpp::FieldTypes::value_type ft = res.field_type(int(i));
			ostringstream os;
			os << ft.sql_name() << " (" << ft.id() << ')';
			cout << setw(widths[0]) << res.field_name(int(i)).c_str() <<
					setw(widths[1]) << os.str() <<
					setw(widths[2]) << cname <<
					endl;
		}


		cout << endl;

		// Simple type check
		if (res.field_type(0) == typeid(string)) {
			cout << "SQL type of 'item' field most closely resembles "
					"the C++ string type." << endl;

		}

		// Tricky type check: the 'if' path shouldn't happen because the
		// description field has the NULL attribute.  We need to dig a
		// little deeper if we want to ignore this in our type checks.
		if (res.field_type(5) == typeid(string)) {
			cout << "Should not happen! Type check failure." << endl;
		}
		else if (res.field_type(5) == typeid(mysqlpp::sql_blob_null)) {

			cout << "SQL type of 'description' field resembles "
					"a nullable variant of the C++ string type." << endl;
		}

		else {
			cout << "Weird: fifth field's type is now " <<
					res.field_type(5).name() << endl;
			cout << "Did something recently change in resetdb?" << endl;

		}


	}
	catch (const mysqlpp::BadQuery& er) {
		// Handle any query errors
		cerr << "Query error: " << er.what() << endl;
		return -1;







	}
	catch (const mysqlpp::Exception& er) {
		// Catch-all for any other MySQL++ exceptions
		cerr << "Error: " << er.what() << endl;
		return -1;
	}

	return 0;
}







>


<


<















|
>
|
|

<
|
|
|
|
|
<
<
<

<
|
<
<
<
>
>
>
>
|
<
<
<
<
<
<
<
|
>
>
|

|
|
<
|
>
|
|
|
<
<
<
<
|
<
>
|
<
|
>
|
<
<
<
>
|
>
>





>
>
>
>
>
>
>









23
24
25
26
27
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
56
57
58
59



60

61



62
63
64
65
66







67
68
69
70
71
72
73

74
75
76
77
78




79

80
81

82
83
84



85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
 License along with MySQL++; if not, write to the Free Software
 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
 USA
***********************************************************************/

#include "cmdline.h"
#include "printdata.h"
#include "stock.h"

#include <iostream>


using namespace std;


int
main(int argc, char *argv[])
{
	// Get database access parameters from command line
	mysqlpp::examples::CommandLine cmdline(argc, argv);
	if (!cmdline) {
		return 1;
	}

	try {
		// Establish the connection to the database server.
		mysqlpp::Connection con(mysqlpp::examples::db_name,
				cmdline.server(), cmdline.user(), cmdline.pass());

		// Build a query to retrieve the stock item that has Unicode
		// characters encoded in UTF-8 form.
		mysqlpp::Query query = con.query("select * from stock ");
		query << "where item = " << mysqlpp::quote << "Nürnberger Brats";


		// Retrieve the row, throwing an exception if it fails.
		mysqlpp::StoreQueryResult res = query.store();
		if (res.empty()) {
			throw mysqlpp::BadQuery("UTF-8 bratwurst item not found in "
					"table, run resetdb");



		}





		// Because there should only be one row in the result set,
		// there's no point in storing the result in an STL container.
		// We can store the first row directly into a stock structure
		// because one of an SSQLS's constructors takes a Row object.
		stock row = res[0];








		// Create a copy so that the replace query knows what the
		// original values are.
		stock orig_row = row;

		// Change the stock object's item to use only 7-bit ASCII, and
		// to deliberately be wider than normal column widths printed

		// by print_stock_table().
		row.item = "Nuerenberger Bratwurst";

		// Form the query to replace the row in the stock table.
		query.update(orig_row, row);






		// Show the query about to be executed.
		cout << "Query: " << query << endl;


		// Run the query with execute(), since UPDATE doesn't return a
		// result set.



		query.execute();

		// Retrieve and print out the new table contents.
		print_stock_table(query);
	}
	catch (const mysqlpp::BadQuery& er) {
		// Handle any query errors
		cerr << "Query error: " << er.what() << endl;
		return -1;
	}
	catch (const mysqlpp::BadConversion& er) {
		// Handle bad conversions
		cerr << "Conversion error: " << er.what() << endl <<
				"\tretrieved data size: " << er.retrieved <<
				", actual size: " << er.actual_size << endl;
		return -1;
	}
	catch (const mysqlpp::Exception& er) {
		// Catch-all for any other MySQL++ exceptions
		cerr << "Error: " << er.what() << endl;
		return -1;
	}

	return 0;
}

Changes to examples/for_each.cpp.

1
2
3
4

5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
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
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
/***********************************************************************
 for_each.cpp - Demonstrates Query::for_each(), showing how to perform
	an arbitrary action on each row in a result set.


 Copyright (c) 2005-2009 by Educational Technology Resources, Inc. and
 (c) 2007 by Switchplane, Ltd.  Others may also hold copyrights on
 code in this file.  See the CREDITS.txt file in the top directory
 of the distribution for details.

 This file is part of MySQL++.

 MySQL++ is free software; you can redistribute it and/or modify it
 under the terms of the GNU Lesser General Public License as published
 by the Free Software Foundation; either version 2.1 of the License, or
 (at your option) any later version.

 MySQL++ is distributed in the hope that it will be useful, but WITHOUT
 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
 License for more details.

 You should have received a copy of the GNU Lesser General Public
 License along with MySQL++; if not, write to the Free Software
 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
 USA
***********************************************************************/

#include "cmdline.h"
#include "printdata.h"
#include "stock.h"

#include <mysql++.h>

#include <iostream>

#include <math.h>


// Define a functor to collect statistics about the stock table
class gather_stock_stats
{
public:
	gather_stock_stats() :
	items_(0),
	weight_(0),
	cost_(0)
	{
	}

	void operator()(const stock& s)
	{
		items_  += s.num;
		weight_ += (s.num * s.weight);
		cost_   += (s.num * s.price.data);
	}
	
private:
	mysqlpp::sql_bigint items_;
	mysqlpp::sql_double weight_, cost_;

	friend std::ostream& operator<<(std::ostream& os,
			const gather_stock_stats& ss);
};


// Dump the contents of gather_stock_stats to a stream in human-readable
// form.
std::ostream&
operator<<(std::ostream& os, const gather_stock_stats& ss)
{
	os << ss.items_ << " items " <<
			"weighing " << ss.weight_ << " stone and " <<
			"costing " << ss.cost_ << " cowrie shells";
	return os;
}


int
main(int argc, char *argv[])
{
	// Get database access parameters from command line
	mysqlpp::examples::CommandLine cmdline(argc, argv);
	if (!cmdline) {
		return 1;
	}

	try {
		// Establish the connection to the database server.
		mysqlpp::Connection con(mysqlpp::examples::db_name,
				cmdline.server(), cmdline.user(), cmdline.pass());

		// Gather and display the stats for the entire stock table
		mysqlpp::Query query = con.query();
		std::cout << "There are " << query.for_each(stock(),
				gather_stock_stats()) << '.' << std::endl;
	}
	catch (const mysqlpp::BadQuery& e) {
		// Something went wrong with the SQL query.
		std::cerr << "Query failed: " << e.what() << std::endl;
		return 1;
	}
	catch (const mysqlpp::Exception& er) {
		// Catch-all for any other MySQL++ exceptions
		std::cerr << "Error: " << er.what() << std::endl;
		return 1;
	}

	return 0;
}

|
|

>
|
<
|
|



















|
|
<



<
|
<
|
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
|
<
|
<
<
<
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
|
<
<
|
<
<
<
<
<
<
<
<
<
<
|
<
|
1
2
3
4
5
6

7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29

30
31
32

33

34
35



















36

37



38




























39


40










41

42
/***********************************************************************
 printdata.h - Declares utility routines for printing out data in
	common forms, used by most of the example programs.

 Copyright (c) 1998 by Kevin Atkinson, (c) 1999-2001 by MySQL AB, and
 (c) 2004-2009 by Educational Technology Resources, Inc.  Others may

 also hold copyrights on code in this file.  See the CREDITS.txt file
 in the top directory of the distribution for details.

 This file is part of MySQL++.

 MySQL++ is free software; you can redistribute it and/or modify it
 under the terms of the GNU Lesser General Public License as published
 by the Free Software Foundation; either version 2.1 of the License, or
 (at your option) any later version.

 MySQL++ is distributed in the hope that it will be useful, but WITHOUT
 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
 License for more details.

 You should have received a copy of the GNU Lesser General Public
 License along with MySQL++; if not, write to the Free Software
 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
 USA
***********************************************************************/

#if !defined(MYSQLPP_PRINTDATA_H)
#define MYSQLPP_PRINTDATA_H


#include <mysql++.h>


void print_stock_header(size_t rows);

void print_stock_row(const mysqlpp::Row& r);
void print_stock_row(const mysqlpp::sql_char& item,



















		mysqlpp::sql_bigint num, mysqlpp::sql_double weight,

		mysqlpp::sql_decimal_null price, const mysqlpp::sql_date& date);



void print_stock_rows(mysqlpp::StoreQueryResult& res);




























void print_stock_table(mysqlpp::Query& query);













#endif // !defined(MYSQLPP_PRINTDATA_H)


Changes to examples/images.h.

1
2

3
4
5
6
7
8
9
10
11
/***********************************************************************
 images.h - Declares the images table SSQLS.


 Copyright (c) 2008-2010 by Educational Technology Resources, Inc.
 Others may also hold copyrights on code in this file.  See the
 CREDITS.txt file in the top directory of the distribution for details.

 This file is part of MySQL++.

 MySQL++ is free software; you can redistribute it and/or modify it
 under the terms of the GNU Lesser General Public License as published

|
>

|







1
2
3
4
5
6
7
8
9
10
11
12
/***********************************************************************
 test/uds.cpp - Tests the Unix domain socket verifier in
	UnixDomainSocketConnection.  This test always succeeds on Windows!

 Copyright (c) 2007-2008 by Educational Technology Resources, Inc.
 Others may also hold copyrights on code in this file.  See the
 CREDITS.txt file in the top directory of the distribution for details.

 This file is part of MySQL++.

 MySQL++ is free software; you can redistribute it and/or modify it
 under the terms of the GNU Lesser General Public License as published
19
20
21
22
23
24
25





26






27



28


29


30








31





32































































































 You should have received a copy of the GNU Lesser General Public
 License along with MySQL++; if not, write to the Free Software
 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
 USA
***********************************************************************/






#include <mysql++.h>






#include <ssqls.h>






sql_create_2(images,


	1, 2,








	mysqlpp::sql_int_unsigned_null, id,





	mysqlpp::sql_blob_null, data)





































































































>
>
>
>
>
|
>
>
>
>
>
>
|
>
>
>

>
>
|
>
>
|
>
>
>
>
>
>
>
>
|
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
20
21
22
23
24
25
26
27
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
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
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
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158

 You should have received a copy of the GNU Lesser General Public
 License along with MySQL++; if not, write to the Free Software
 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
 USA
***********************************************************************/

#include <connection.h>
#include <exceptions.h>

#include <iostream>
#include <sstream>
#include <string>

#if !defined(MYSQLPP_PLATFORM_WINDOWS)
#include <unistd.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/socket.h>
#include <sys/un.h>
#if !defined(AF_LOCAL)
#	define AF_LOCAL AF_UNIX
#endif

#include <errno.h>
#include <string.h>

static const char* success_path = "test_uds_success.sock";
static const char* failure_path = "test_uds_failure.sock";

static int
make_socket(const char* path, mode_t mode)
{
	// Just in case a socket with this name exists already, try to
	// remove it.  Only a failure if it exists and we can't remove it.
	if ((unlink(path) < 0) && (errno != ENOENT)) {
		return -1;
	}

	// Create the domain socket
	int fd = socket(AF_LOCAL, SOCK_STREAM, 0);
	if (fd < 0) {
		return -1;
	}
	
	// Bind the socket to the named file
	struct sockaddr_un saun;
	memset(&saun, 0, sizeof(saun));
	saun.sun_family = AF_LOCAL;
	strncpy(saun.sun_path, path, sizeof(saun.sun_path));
	saun.sun_path[sizeof(saun.sun_path) - 1] = '\0';
	if (bind(fd, reinterpret_cast<sockaddr*>(&saun), sizeof(saun)) < 0) {
		return -1;
	}

	// Change the socket's mode as requested
	if (chmod(path, mode) < 0) {
		return -1;
	}

	return fd;
}

	
static void
test_success()
{
	std::string error;
	int fd = make_socket(success_path, S_IREAD | S_IWRITE);
	if (fd >= 0) {
		bool fail = !mysqlpp::UnixDomainSocketConnection::is_socket(
				success_path, &error);
		if (fail) {
			throw mysqlpp::SelfTestFailed(error);
		}
	}
	else {
		std::ostringstream outs;
		outs << "Failed to create test domain socket: " << strerror(errno);
		throw mysqlpp::SelfTestFailed(outs.str());
	}
}


static void
test_failure()
{
	int fd = make_socket(failure_path, S_IREAD);
	if (fd < 0) {
		std::ostringstream outs;
		outs << "Failed to create test domain socket: " << strerror(errno);
		throw mysqlpp::SelfTestFailed(outs.str());
	}

	if (mysqlpp::UnixDomainSocketConnection::is_socket(failure_path)) {
		throw mysqlpp::SelfTestFailed("Failed to fail on read-only socket");
	}
	else if (mysqlpp::UnixDomainSocketConnection::is_socket(
			"BogusBogus.sock")) {
		throw mysqlpp::SelfTestFailed("Failed to fail on bad file name");
	}
	else {
		close(fd);
		unlink(failure_path);
		fd = creat(failure_path, S_IREAD | S_IWRITE);
		bool success = mysqlpp::UnixDomainSocketConnection::is_socket(
				failure_path);
		if (success) {
			throw mysqlpp::SelfTestFailed("Failed to fail on non-socket");
		}
	}
}
#endif


int
main()
{
#if defined(MYSQLPP_PLATFORM_WINDOWS)
	// Test not appropriate to this platform.  Always succeed.
	return 0;
#else
	try {
		test_success();
		unlink(success_path);
		test_failure();
		unlink(failure_path);
		return 0;
	}
	catch (mysqlpp::SelfTestFailed& e) {
		std::cerr << "TCP address parse error: " << e.what() << std::endl;
		return 1;
	}
	catch (std::exception& e) {
		std::cerr << "Unexpected test failure: " << e.what() << std::endl;
		return 2;
	}
#endif
}

Changes to examples/load_jpeg.cpp.

1
2
3
4
5
6
7
8
9
10
/***********************************************************************
 load_jpeg.cpp - Example showing how to insert BLOB data into the
	database from a file.

 Copyright (c) 1998 by Kevin Atkinson, (c) 1999-2001 by MySQL AB, and
 (c) 2004-2009 by Educational Technology Resources, Inc.  Others may
 also hold copyrights on code in this file.  See the CREDITS.txt file
 in the top directory of the distribution for details.

 This file is part of MySQL++.

|
|







1
2
3
4
5
6
7
8
9
10
/***********************************************************************
 printdata.cpp - Utility functions for printing out data in common
	formats, required by most of the example programs.

 Copyright (c) 1998 by Kevin Atkinson, (c) 1999-2001 by MySQL AB, and
 (c) 2004-2009 by Educational Technology Resources, Inc.  Others may
 also hold copyrights on code in this file.  See the CREDITS.txt file
 in the top directory of the distribution for details.

 This file is part of MySQL++.
21
22
23
24
25
26
27
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
56
57
58
59
60
61
62
63

64

65
66
67
68
69
70
71
72
73


74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94



95
96

97
98

99
100
101
102
103
104
105
106

107
108
109
110
111

112



113
114
115
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

144

145
146

147
148
149
150

151
152
153
154
155
156
157
158
159
160
161

162
163

 You should have received a copy of the GNU Lesser General Public
 License along with MySQL++; if not, write to the Free Software
 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
 USA
***********************************************************************/

#include "cmdline.h"
#include "images.h"
#include "printdata.h"

#include <fstream>


using namespace std;
using namespace mysqlpp;




// This is just an implementation detail for the example.  Skip down to
// main() for the concept this example is trying to demonstrate.  You
// can simply assume that, given a BLOB containing a valid JPEG, it
// returns true.
static bool
is_jpeg(const mysqlpp::sql_blob& img, const char** whynot)

{



	// See http://stackoverflow.com/questions/2253404/ for
	// justification for the various tests.
	const unsigned char* idp =
			reinterpret_cast<const unsigned char*>(img.data());
	if (img.size() < 125) {
		*whynot = "a valid JPEG must be at least 125 bytes";

	}
	else if ((idp[0] != 0xFF) || (idp[1] != 0xD8)) {
		*whynot = "file does not begin with JPEG sigil bytes";
	}
	else if ((memcmp(idp + 6, "JFIF", 4) != 0) &&
			 (memcmp(idp + 6, "Exif", 4) != 0)) {
		*whynot = "file does not contain JPEG type word";
	}
	else {
		*whynot = 0;
		return true;
	}


	return false;

}


// Skip to main() before studying this.  This is a little too
// low-level to bother with on your first pass thru the code.
static bool
load_jpeg_file(const mysqlpp::examples::CommandLine& cmdline,
		images& img, string& img_name)
{


	if (cmdline.extra_args().size() == 0) {
		// Nothing for us to do here.  Caller will insert NULL BLOB.
		return true;
	}

	// Got a file's name on the command line, so open it.
	img_name = cmdline.extra_args()[0];
	ifstream img_file(img_name.c_str(), ios::binary);
	if (img_file) {
		// Slurp file contents into RAM with minimum copying.  (Idiom
		// explained here: http://stackoverflow.com/questions/116038/)
		//
		// By loading the file into a C++ string (stringstream::str())
		// and assigning that directly to a mysqlpp::sql_blob, we avoid
		// truncating the binary data at the first null character.
		img.data.data = static_cast<const stringstream*>(
				&(stringstream() << img_file.rdbuf()))->str();

		// Check JPEG data for sanity.
		const char* error;
		if (is_jpeg(img.data.data, &error)) {



			return true;
		}

		else {
			cerr << '"' << img_name << "\" isn't a JPEG: " <<

					error << '!' << endl;
		}
	}

	cmdline.print_usage("[jpeg_file]");
	return false;
}



int
main(int argc, char *argv[])
{
	// Get database access parameters from command line

	mysqlpp::examples::CommandLine cmdline(argc, argv);



	if (!cmdline) {
		return 1;
	}

	try {
		// Establish the connection to the database server.
		mysqlpp::Connection con(mysqlpp::examples::db_name,
				cmdline.server(), cmdline.user(), cmdline.pass());

		// Load the file named on the command line
		images img(mysqlpp::null, mysqlpp::null);
		string img_name("NULL");
		if (load_jpeg_file(cmdline, img, img_name)) {
			// Insert image data or SQL NULL into the images.data BLOB
			// column.  The key here is that we're holding the raw
			// binary data in a mysqlpp::sql_blob, which avoids data
			// conversion problems that can lead to treating BLOB data
			// as C strings, thus causing null-truncation.  The fact
			// that we're using SSQLS here is a side issue, simply
			// demonstrating that mysqlpp::Null<mysqlpp::sql_blob> is
			// now legal in SSQLS, as of MySQL++ 3.0.7.
			Query query = con.query();
			query.insert(img);
			SimpleResult res = query.execute();

			// Report successful insertion
			cout << "Inserted \"" << img_name <<
					"\" into images table, " << img.data.data.size() <<
					" bytes, ID " << res.insert_id() << endl;
		}


	}

	catch (const BadQuery& er) {

		// Handle any query errors
		cerr << "Query error: " << er.what() << endl;

		return -1;
	}
	catch (const BadConversion& er) {
		// Handle bad conversions

		cerr << "Conversion error: " << er.what() << endl <<
				"\tretrieved data size: " << er.retrieved <<
				", actual size: " << er.actual_size << endl;
		return -1;
	}
	catch (const Exception& er) {
		// Catch-all for any other MySQL++ exceptions
		cerr << "Error: " << er.what() << endl;
		return -1;
	}


	return 0;
}







<
<


|
>


|

>
>

<
<
<
<
|
<
>

>
>
>
|
|
<
<
|
<
>
|
<
<
<
<
<
<
<
<
<
<
|

>
|
>
|
|
|
<
|
<
|
<

>
>
|
|
|
|

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

<
<
<
>
>
>
<
|
>
|
<
>
|
|
|

|
|
|
|
>
|
|
<
|
|
>
|
>
>
>
|
<

|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<

<
<
<
<
|
>
>
|
>
|
>
|
<
>
|
|
<
<
>
|
|
<
<
|
<
<
<
<
<
|
>
|

21
22
23
24
25
26
27


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
56
57

58

59

60
61
62
63
64
65
66
67












68



69
70
71

72
73
74

75
76
77
78
79
80
81
82
83
84
85
86

87
88
89
90
91
92
93
94

95
96




















97




98
99
100
101
102
103
104
105

106
107
108


109
110
111


112





113
114
115
116

 You should have received a copy of the GNU Lesser General Public
 License along with MySQL++; if not, write to the Free Software
 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
 USA
***********************************************************************/



#include "printdata.h"

#include <iostream>
#include <iomanip>

using namespace std;


//// print_stock_header ////////////////////////////////////////////////
// Display a header suitable for use with print_stock_rows().





void

print_stock_header(size_t rows)
{
	cout << "Records found: " << rows << endl << endl;
	cout.setf(ios::left);
	cout << setw(31) << "Item" <<
			setw(10) << "Num" <<
			setw(10) << "Weight" <<


			setw(10) << "Price" <<

			"Date" << endl << endl;
}












//// print_stock_row ///////////////////////////////////////////////////
// Print out a row of data from the stock table, in a format compatible
// with the header printed out in the previous function.

void
print_stock_row(const mysqlpp::sql_char& item, mysqlpp::sql_bigint num,

		mysqlpp::sql_double weight, mysqlpp::sql_decimal_null price,

		const mysqlpp::sql_date& date)

{
	cout << setw(30) << item << ' ' <<
			setw(9) << num << ' ' <<
			setw(9) << weight << ' ' <<
			setw(9) << price << ' ' <<
			date << endl;
}

















//// print_stock_row ///////////////////////////////////////////////////
// Take a Row from the example 'stock' table, break it up into fields,
// and call the above version of this function.


void
print_stock_row(const mysqlpp::Row& row)

{
	print_stock_row(string(row[0]), row[1], row[2], row[3], row[4]);
}


//// print_stock_rows //////////////////////////////////////////////////
// Print out a number of rows from the example 'stock' table.

void
print_stock_rows(mysqlpp::StoreQueryResult& res)
{
	print_stock_header(res.size());


	// Use the StoreQueryResult class's read-only random access iterator to walk
	// through the query results.
	mysqlpp::StoreQueryResult::iterator i;
	for (i = res.begin(); i != res.end(); ++i) {
		// Notice that a dereferenced result iterator can be converted
		// to a Row object, which makes for easier element access.
		print_stock_row(*i);

	}
}


























//// print_stock_table /////////////////////////////////////////////////
// Simply retrieve and print the entire contents of the stock table.

void
print_stock_table(mysqlpp::Query& query)
{
	// Reset query object to its pristine state in case it's been used

	// before by our caller for template queries.
	query.reset();



	// Build the query itself, and show it to the user
	query << "select * from stock";
	cout << "Query: " << query << endl;








	// Execute it, and display the results
	mysqlpp::StoreQueryResult res = query.store();
	print_stock_rows(res);
}

Changes to examples/logo.jpg.

cannot compute difference between binary files

Changes to examples/multiquery.cpp.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
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

56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81

82
83

84
85
86
87
88
89
90
91
92
93
94


95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113


114
115
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
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
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
/***********************************************************************
 multiquery.cpp - Example showing how to iterate over result sets upon
	execution of a query that returns more than one result set.  You can
	get multiple result sets when executing multiple separate SQL
	statments in a single query, or when dealing with the results of
	calling a stored procedure.

 Copyright (c) 1998 by Kevin Atkinson, (c) 1999-2001 by MySQL AB,
 (c) 2004-2009 by Educational Technology Resources, Inc., and (c)
 2005 by Arnon Jalon.  Others may also hold copyrights on code in
 this file.  See the CREDITS.txt file in the top directory of the
 distribution for details.

 This file is part of MySQL++.

 MySQL++ is free software; you can redistribute it and/or modify it
 under the terms of the GNU Lesser General Public License as published
 by the Free Software Foundation; either version 2.1 of the License, or
 (at your option) any later version.

 MySQL++ is distributed in the hope that it will be useful, but WITHOUT
 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
 License for more details.

 You should have received a copy of the GNU Lesser General Public
 License along with MySQL++; if not, write to the Free Software
 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
 USA
***********************************************************************/

#include "cmdline.h"
#include "printdata.h"

#include <mysql++.h>

#include <algorithm>
#include <iostream>
#include <iomanip>
#include <vector>

using namespace std;
using namespace mysqlpp;


typedef vector<size_t> IntVectorType;


static void
print_header(IntVectorType& widths, StoreQueryResult& res)

{
	cout << "  |" << setfill(' ');


	for (size_t i = 0; i < res.field_names()->size(); i++) {
		cout << " " << setw(widths.at(i)) << res.field_name(int(i)) << " |";


	}

	cout << endl;
}


static void
print_row(IntVectorType& widths, Row& row)
{
	cout << "  |" << setfill(' ');
	for (size_t i = 0; i < row.size(); ++i) {
		cout << " " << setw(widths.at(i)) << row[int(i)] << " |";
	}
	cout << endl;
}


static void
print_row_separator(IntVectorType& widths)
{
	cout << "  +" << setfill('-');
	for (size_t i = 0; i < widths.size(); i++) {
		cout << "-" << setw(widths.at(i)) << '-' << "-+";
	}
	cout << endl;
}



static void
print_result(StoreQueryResult& res, int index)

{
	// Show how many rows are in result, if any
	StoreQueryResult::size_type num_results = res.size();
	if (res && (num_results > 0)) {
		cout << "Result set " << index << " has " << num_results <<
				" row" << (num_results == 1 ? "" : "s") << ':' << endl;
	}
	else {
		cout << "Result set " << index << " is empty." << endl;
		return;
	}



	// Figure out the widths of the result set's columns
	IntVectorType widths;
	size_t size = res.num_fields();
	for (size_t i = 0; i < size; i++) {
		widths.push_back(max(
				res.field(i).max_length(),
				res.field_name(i).size()));
	}

	// Print result set header
	print_row_separator(widths);
	print_header(widths, res);
	print_row_separator(widths);

	// Display the result set contents
	for (StoreQueryResult::size_type i = 0; i < num_results; ++i) {
		print_row(widths, res[i]);
	}



	// Print result set footer
	print_row_separator(widths);


}


static void
print_multiple_results(Query& query)

{
	// Execute query and print all result sets
	StoreQueryResult res = query.store();
	print_result(res, 0);
	for (int i = 1; query.more_results(); ++i) {
		res = query.store_next();
		print_result(res, i);
	}
}


int
main(int argc, char *argv[])
{
	// Get connection parameters from command line
	mysqlpp::examples::CommandLine cmdline(argc, argv);
	if (!cmdline) {
		return 1;
	}

	try {
		// Enable multi-queries.  Notice that you almost always set
		// MySQL++ connection options before establishing the server
		// connection, and options are always set using this one
		// interface.  If you're familiar with the underlying C API,
		// you know that there is poor consistency on these matters;
		// MySQL++ abstracts these differences away.
		Connection con;
		con.set_option(new MultiStatementsOption(true));

		// Connect to the database
		if (!con.connect(mysqlpp::examples::db_name, cmdline.server(),
				cmdline.user(), cmdline.pass())) {
			return 1;
		}

		// Set up query with multiple queries.
		Query query = con.query();
		query << "DROP TABLE IF EXISTS test_table; " <<
				"CREATE TABLE test_table(id INT); " <<
				"INSERT INTO test_table VALUES(10); " <<
				"UPDATE test_table SET id=20 WHERE id=10; " <<
				"SELECT * FROM test_table; " <<
				"DROP TABLE test_table";
		cout << "Multi-query: " << endl << query << endl;

		// Execute statement and display all result sets.
		print_multiple_results(query);

#if MYSQL_VERSION_ID >= 50000
		// If it's MySQL v5.0 or higher, also test stored procedures, which
		// return their results the same way multi-queries do.
		query << "DROP PROCEDURE IF EXISTS get_stock; " <<
				"CREATE PROCEDURE get_stock" <<
				"( i_item varchar(20) ) " <<
				"BEGIN " <<
				"SET i_item = concat('%', i_item, '%'); " <<
				"SELECT * FROM stock WHERE lower(item) like lower(i_item); " <<
				"END;";
		cout << "Stored procedure query: " << endl << query << endl;

		// Create the stored procedure.
		print_multiple_results(query);

		// Call the stored procedure and display its results.
		query << "CALL get_stock('relish')";
		cout << "Query: " << query << endl;
		print_multiple_results(query);
#endif

		return 0;
	}
	catch (const BadOption& err) {
		cerr << err.what() << endl;
		cerr << "This example requires MySQL 4.1.1 or later." << endl;
		return 1;
	}
	catch (const ConnectionFailed& err) {
		cerr << "Failed to connect to database server: " <<
				err.what() << endl;
		return 1;
	}
	catch (const Exception& er) {
		// Catch-all for any other MySQL++ exceptions
		cerr << "Error: " << er.what() << endl;
		return 1;
	}
}

|
<
<
<
|

<
|
|
|
<



















<
<
<


|

<
<

<
<
|

<

|
|
<
>

<
>
>
|
<
>
>
|
>
<
|
|
|
<
<
<
<
<
<

|
<
|
|
<
<
<
|
<
<

<



>
|
<
>

<
|
|
|
|
|
|
<
<
|
>
>
|
|
|
<
<
<
<
<
|
<
<
<
<
<

<
<
<
|
>
>
|
<
<
>
>



|
<
>

<
<
|
<
<
|
<




|

<
<
<
<
<
<

<
<
<
<
<
<
<
<
<
<
<
<
|
|
|
<
<
<
<
<
<
<
<
<
|
<
<
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
|

<
<
<
<
|
<
<
<
<
|
<
<
<
<
<
<
1
2



3
4

5
6
7

8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26



27
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
56
57
58
59

60
61

62
63
64
65
66
67


68
69
70
71
72
73





74





75



76
77
78
79


80
81
82
83
84
85

86
87


88


89

90
91
92
93
94
95






96












97
98
99









100


101





















102
103




104




105






/***********************************************************************
 test/insertpolicy.cpp - Checks that the *InsertPolicy objects work



 	as expected.


 Copyright (c) 2009 by Educational Technology Resources, Inc.
 Others may also hold copyrights on code in this file.  See the
 CREDITS.txt file in the top directory of the distribution for details.


 This file is part of MySQL++.

 MySQL++ is free software; you can redistribute it and/or modify it
 under the terms of the GNU Lesser General Public License as published
 by the Free Software Foundation; either version 2.1 of the License, or
 (at your option) any later version.

 MySQL++ is distributed in the hope that it will be useful, but WITHOUT
 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
 License for more details.

 You should have received a copy of the GNU Lesser General Public
 License along with MySQL++; if not, write to the Free Software
 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
 USA
***********************************************************************/




#include <mysql++.h>

#include <climits>
#include <iostream>





static const unsigned char nonzero = 4;



template <class InsertPolicy>
static bool

test_policy(InsertPolicy& ip, unsigned char max, bool expected_to_fail)
{

	unsigned char i;
	mysqlpp::Row dummy;
	for (i = 0; i < UCHAR_MAX; ++i) {

		if (!ip.can_add(i, dummy)) {
			break;
		}
	}


	if (expected_to_fail ? i != max : i == max) {
		return true;






	}
	else {

		std::cerr << typeid(ip).name() << '(' << int(max) << 
				") allowed " << int(i) << " inserts!" << std::endl;



		return false;


	}

}


template <class InsertPolicy>
static bool

test_policy(InsertPolicy& ip, unsigned char expected_allow_count)
{

	return	test_policy(ip, expected_allow_count, false) &&
			test_policy(ip, expected_allow_count + 1, true) &&
			test_policy(ip, expected_allow_count - 1, true) &&
			test_policy(ip, expected_allow_count ? 0 : nonzero, true);
}




static bool
test_row_count_nonzero()
{
	mysqlpp::Query::RowCountInsertPolicy<> ip_nonzero(nonzero);
	return test_policy(ip_nonzero, nonzero);





}










static bool
test_row_count_zero()
{


	mysqlpp::Query::RowCountInsertPolicy<> ip_zero(0);
	return test_policy(ip_zero, 0);
}


static bool

test_row_count()
{


	return	test_row_count_nonzero() &&


			test_row_count_zero();

}


int
main()
{






	try {












		return test_row_count() ? 0 : 1;
	}
	catch (...) {









		std::cerr << "Unhandled exception caught by "


				"test/insertpolicy!" << std::endl;





















		return 2;
	}




}











Changes to examples/printdata.cpp.

1
2
3


4
5
6
7
8
9
10
11
12
13
/***********************************************************************
 printdata.cpp - Utility functions for printing out data in common
	formats, required by most of the example programs.



 Copyright (c) 1998 by Kevin Atkinson, (c) 1999-2001 by MySQL AB, and
 (c) 2004-2009 by Educational Technology Resources, Inc.  Others may
 also hold copyrights on code in this file.  See the CREDITS.txt file
 in the top directory of the distribution for details.

 This file is part of MySQL++.

 MySQL++ is free software; you can redistribute it and/or modify it
 under the terms of the GNU Lesser General Public License as published

|
|
>
>


|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/***********************************************************************
 ssqls4.cpp - Example very similar to ssqls1.cpp, except that it
	stores its result set in an STL set container.  This demonstrates
	how one can manipulate MySQL++ result sets in a very natural C++
	style.

 Copyright (c) 1998 by Kevin Atkinson, (c) 1999-2001 by MySQL AB, and
 (c) 2004-2010 by Educational Technology Resources, Inc.  Others may
 also hold copyrights on code in this file.  See the CREDITS.txt file
 in the top directory of the distribution for details.

 This file is part of MySQL++.

 MySQL++ is free software; you can redistribute it and/or modify it
 under the terms of the GNU Lesser General Public License as published
21
22
23
24
25
26
27

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
56
57
58

59
60
61
62
63
64
65
66
67
68

69
70
71



72
73
74
75
76





77
78

79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99

100


101
102
103
104

105
106
107
108
109
110
111
112
113
114
115
116

 You should have received a copy of the GNU Lesser General Public
 License along with MySQL++; if not, write to the Free Software
 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
 USA
***********************************************************************/


#include "printdata.h"


#include <iostream>
#include <iomanip>

using namespace std;


//// print_stock_header ////////////////////////////////////////////////
// Display a header suitable for use with print_stock_rows().

void
print_stock_header(size_t rows)
{
	cout << "Records found: " << rows << endl << endl;
	cout.setf(ios::left);
	cout << setw(31) << "Item" <<


			setw(10) << "Num" <<
			setw(10) << "Weight" <<
			setw(10) << "Price" <<
			"Date" << endl << endl;
}


//// print_stock_row ///////////////////////////////////////////////////
// Print out a row of data from the stock table, in a format compatible
// with the header printed out in the previous function.



void
print_stock_row(const mysqlpp::sql_char& item, mysqlpp::sql_bigint num,
		mysqlpp::sql_double weight, mysqlpp::sql_decimal_null price,

		const mysqlpp::sql_date& date)
{
	cout << setw(30) << item << ' ' <<
			setw(9) << num << ' ' <<
			setw(9) << weight << ' ' <<
			setw(9) << price << ' ' <<
			date << endl;
}



//// print_stock_row ///////////////////////////////////////////////////
// Take a Row from the example 'stock' table, break it up into fields,
// and call the above version of this function.




void
print_stock_row(const mysqlpp::Row& row)
{
	print_stock_row(string(row[0]), row[1], row[2], row[3], row[4]);





}



//// print_stock_rows //////////////////////////////////////////////////
// Print out a number of rows from the example 'stock' table.

void
print_stock_rows(mysqlpp::StoreQueryResult& res)
{
	print_stock_header(res.size());

	// Use the StoreQueryResult class's read-only random access iterator to walk
	// through the query results.
	mysqlpp::StoreQueryResult::iterator i;
	for (i = res.begin(); i != res.end(); ++i) {
		// Notice that a dereferenced result iterator can be converted
		// to a Row object, which makes for easier element access.
		print_stock_row(*i);
	}
}


//// print_stock_table /////////////////////////////////////////////////

// Simply retrieve and print the entire contents of the stock table.



void
print_stock_table(mysqlpp::Query& query)
{

	// Reset query object to its pristine state in case it's been used
	// before by our caller for template queries.
	query.reset();

	// Build the query itself, and show it to the user
	query << "select * from stock";
	cout << "Query: " << query << endl;

	// Execute it, and display the results
	mysqlpp::StoreQueryResult res = query.store();
	print_stock_rows(res);
}







>

>


<



|
<
<
|
<
<

<
<
<
>
>
|
<
|
<
|

|
<
<
|
>
>

|
|
|
>
|
<
|
|
<
<
<
|
|
|
>
|
|
|
>
>
>
|
<
<
|
|
>
>
>
>
>
|
|
>
|
<
<
|
<
|
<
<
|
<
|
|
<
<
<
<

<
|
|
<
>
|
>
>
|
<
|
<
>
|
<
|
|
<
<
<

<
<
|

23
24
25
26
27
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
56

57
58



59
60
61
62
63
64
65
66
67
68
69


70
71
72
73
74
75
76
77
78
79
80


81

82


83

84
85




86

87
88

89
90
91
92
93

94

95
96

97
98



99


100
101

 You should have received a copy of the GNU Lesser General Public
 License along with MySQL++; if not, write to the Free Software
 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
 USA
***********************************************************************/

#include "cmdline.h"
#include "printdata.h"
#include "stock.h"

#include <iostream>


using namespace std;

int


main(int argc, char *argv[])


{



	// Get database access parameters from command line
	mysqlpp::examples::CommandLine cmdline(argc, argv);
	if (!cmdline) {

		return 1;

	}

	try {


		// Establish the connection to the database server.
		mysqlpp::Connection con(mysqlpp::examples::db_name,
				cmdline.server(), cmdline.user(), cmdline.pass());

		// Retrieve all rows from the stock table and put them in an
		// STL set.  Notice that this works just as well as storing them
		// in a vector, which we did in ssqls1.cpp.  It works because
		// SSQLS objects are less-than comparable.
		mysqlpp::Query query = con.query("select * from stock");

		set<stock> res;
		query.storein(res);




		// Display the result set.  Since it is an STL set and we set up
		// the SSQLS to compare based on the item column, the rows will
		// be sorted by item.
		print_stock_header(res.size());
		set<stock>::iterator it;
		cout.precision(3);
		for (it = res.begin(); it != res.end(); ++it) {
			print_stock_row(it->item.c_str(), it->num, it->weight,
					it->price, it->sDate);
		}



		// Use set's find method to look up a stock item by item name.
		// This also uses the SSQLS comparison setup.
		it = res.find(stock("Hotdog Buns"));
		if (it != res.end()) {
			cout << endl << "Currently " << it->num <<
					" hotdog buns in stock." << endl;
		}
		else {
			cout << endl << "Sorry, no hotdog buns in stock." << endl;
		}


	}

	catch (const mysqlpp::BadQuery& er) {


		// Handle any query errors

		cerr << "Query error: " << er.what() << endl;
		return -1;




	}

	catch (const mysqlpp::BadConversion& er) {
		// Handle bad conversions

		cerr << "Conversion error: " << er.what() << endl <<
				"\tretrieved data size: " << er.retrieved <<
				", actual size: " << er.actual_size << endl;
		return -1;
	}

	catch (const mysqlpp::Exception& er) {

		// Catch-all for any other MySQL++ exceptions
		cerr << "Error: " << er.what() << endl;

		return -1;
	}






	return 0;
}

Changes to examples/printdata.h.

1
2
3

4
5
6
7
8

9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29

30

31
32

33




34



35




36




37





38




39



40












41

42
/***********************************************************************
 printdata.h - Declares utility routines for printing out data in
	common forms, used by most of the example programs.


 Copyright (c) 1998 by Kevin Atkinson, (c) 1999-2001 by MySQL AB, and
 (c) 2004-2009 by Educational Technology Resources, Inc.  Others may
 also hold copyrights on code in this file.  See the CREDITS.txt file
 in the top directory of the distribution for details.


 This file is part of MySQL++.

 MySQL++ is free software; you can redistribute it and/or modify it
 under the terms of the GNU Lesser General Public License as published
 by the Free Software Foundation; either version 2.1 of the License, or
 (at your option) any later version.

 MySQL++ is distributed in the hope that it will be useful, but WITHOUT
 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
 License for more details.

 You should have received a copy of the GNU Lesser General Public
 License along with MySQL++; if not, write to the Free Software
 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
 USA
***********************************************************************/

#if !defined(MYSQLPP_PRINTDATA_H)
#define MYSQLPP_PRINTDATA_H



#include <mysql++.h>


void print_stock_header(size_t rows);




void print_stock_row(const mysqlpp::Row& r);



void print_stock_row(const mysqlpp::sql_char& item,




		mysqlpp::sql_bigint num, mysqlpp::sql_double weight,




		mysqlpp::sql_decimal_null price, const mysqlpp::sql_date& date);





void print_stock_rows(mysqlpp::StoreQueryResult& res);




void print_stock_table(mysqlpp::Query& query);
















#endif // !defined(MYSQLPP_PRINTDATA_H)



<
|
>

|
|
|
|
>



















|
|
>

>
|

>
|
>
>
>
>
|
>
>
>
|
>
>
>
>
|
>
>
>
>
|
>
>
>
>
>
|
>
>
>
>
|
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
|
>
|
1

2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
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
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
/***********************************************************************

 ssqls5.cpp - Example showing how to use the equal_list() member of
	some SSQLS types to build SELECT queries with custom WHERE clauses.

 Copyright (c) 1998 by Kevin Atkinson, (c) 1999-2001 by MySQL AB, (c)
 2004-2009 by Educational Technology Resources, Inc., and (c) 2005 by
 Chris Frey.  Others may also hold copyrights on code in this file.
 See the CREDITS.txt file in the top directory of the distribution
 for details.

 This file is part of MySQL++.

 MySQL++ is free software; you can redistribute it and/or modify it
 under the terms of the GNU Lesser General Public License as published
 by the Free Software Foundation; either version 2.1 of the License, or
 (at your option) any later version.

 MySQL++ is distributed in the hope that it will be useful, but WITHOUT
 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
 License for more details.

 You should have received a copy of the GNU Lesser General Public
 License along with MySQL++; if not, write to the Free Software
 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
 USA
***********************************************************************/

#include "cmdline.h"
#include "printdata.h"
#include "stock.h"

#include <iostream>
#include <vector>

using namespace std;

int
main(int argc, char *argv[])
{
	// Get database access parameters from command line
	mysqlpp::examples::CommandLine cmdline(argc, argv);
	if (!cmdline) {
		return 1;
	}

	try {
		// Establish the connection to the database server.
		mysqlpp::Connection con(mysqlpp::examples::db_name,
				cmdline.server(), cmdline.user(), cmdline.pass());

		// Get all the rows in the stock table.
		mysqlpp::Query query = con.query("select * from stock");
		vector<stock> res;
		query.storein(res);

		if (res.size() > 0) {
			// Build a select query using the data from the first row
			// returned by our previous query.
			query << "select * from stock where " <<
					res[0].equal_list(" and ", stock_weight, stock_price);

			// Display the finished query.
			cout << "Custom query:\n" << query << endl;
		}
	}
	catch (const mysqlpp::BadQuery& er) {
		// Handle any query errors
		cerr << "Query error: " << er.what() << endl;
		return -1;
	}
	catch (const mysqlpp::BadConversion& er) {
		// Handle bad conversions
		cerr << "Conversion error: " << er.what() << endl <<
				"\tretrieved data size: " << er.retrieved <<
				", actual size: " << er.actual_size << endl;
		return -1;
	}
	catch (const mysqlpp::Exception& er) {
		// Catch-all for any other MySQL++ exceptions
		cerr << "Error: " << er.what() << endl;
		return -1;
	}

	return 0;
}

Changes to examples/simple1.cpp.

1
2
3
4
5
6
7
8
9
10
/***********************************************************************
 simple1.cpp - Example showing the simplest way to get data from a MySQL
	table with MySQL++.

 Copyright (c) 1998 by Kevin Atkinson, (c) 1999-2001 by MySQL AB, and
 (c) 2004-2009 by Educational Technology Resources, Inc.  Others may
 also hold copyrights on code in this file.  See the CREDITS.txt file
 in the top directory of the distribution for details.

 This file is part of MySQL++.

|
|







1
2
3
4
5
6
7
8
9
10
/***********************************************************************
 load_jpeg.cpp - Example showing how to insert BLOB data into the
	database from a file.

 Copyright (c) 1998 by Kevin Atkinson, (c) 1999-2001 by MySQL AB, and
 (c) 2004-2009 by Educational Technology Resources, Inc.  Others may
 also hold copyrights on code in this file.  See the CREDITS.txt file
 in the top directory of the distribution for details.

 This file is part of MySQL++.
22
23
24
25
26
27
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
56
57
58

59


60
61

62
63
64
65
66




67
68
69


70
71
72


73
 You should have received a copy of the GNU Lesser General Public
 License along with MySQL++; if not, write to the Free Software
 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
 USA
***********************************************************************/

#include "cmdline.h"

#include "printdata.h"

#include <mysql++.h>



#include <iostream>
#include <iomanip>

























using namespace std;












































int
main(int argc, char *argv[])
{
	// Get database access parameters from command line
	mysqlpp::examples::CommandLine cmdline(argc, argv);
	if (!cmdline) {
		return 1;
	}


	// Connect to the sample database.
	mysqlpp::Connection conn(false);
	if (conn.connect(mysqlpp::examples::db_name, cmdline.server(),
			cmdline.user(), cmdline.pass())) {
		// Retrieve a subset of the sample stock table set up by resetdb








		// and display it.



		mysqlpp::Query query = conn.query("select item from stock");

		if (mysqlpp::StoreQueryResult res = query.store()) {
			cout << "We have:" << endl;
			mysqlpp::StoreQueryResult::const_iterator it;
			for (it = res.begin(); it != res.end(); ++it) {
				mysqlpp::Row row = *it;

				cout << '\t' << row[0] << endl;


			}
		}

		else {
			cerr << "Failed to get item list: " << query.error() << endl;
			return 1;
		}





		return 0;
	}
	else {


		cerr << "DB connection failed: " << conn.error() << endl;
		return 1;
	}


}







>


|

>
>
|
|
>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>










>
|
|
<
|
|
>
>
>
>
>
>
>
>
|
>
>
>
|
>
|
|
<
<
<
>
|
>
>
|
|
>
|
|
|
|
|
>
>
>
>
|

<
>
>
|
|

>
>

22
23
24
25
26
27
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
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
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
144
145
146
147
148
149
150
151
152
153
154
155

156
157
158
159
160
161
162
163
 You should have received a copy of the GNU Lesser General Public
 License along with MySQL++; if not, write to the Free Software
 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
 USA
***********************************************************************/

#include "cmdline.h"
#include "images.h"
#include "printdata.h"

#include <fstream>

using namespace std;
using namespace mysqlpp;


// This is just an implementation detail for the example.  Skip down to
// main() for the concept this example is trying to demonstrate.  You
// can simply assume that, given a BLOB containing a valid JPEG, it
// returns true.
static bool
is_jpeg(const mysqlpp::sql_blob& img, const char** whynot)
{
	// See http://stackoverflow.com/questions/2253404/ for
	// justification for the various tests.
	const unsigned char* idp =
			reinterpret_cast<const unsigned char*>(img.data());
	if (img.size() < 125) {
		*whynot = "a valid JPEG must be at least 125 bytes";
	}
	else if ((idp[0] != 0xFF) || (idp[1] != 0xD8)) {
		*whynot = "file does not begin with JPEG sigil bytes";
	}
	else if ((memcmp(idp + 6, "JFIF", 4) != 0) &&
			 (memcmp(idp + 6, "Exif", 4) != 0)) {
		*whynot = "file does not contain JPEG type word";
	}
	else {
		*whynot = 0;
		return true;
	}

	return false;
}


// Skip to main() before studying this.  This is a little too
// low-level to bother with on your first pass thru the code.
static bool
load_jpeg_file(const mysqlpp::examples::CommandLine& cmdline,
		images& img, string& img_name)
{
	if (cmdline.extra_args().size() == 0) {
		// Nothing for us to do here.  Caller will insert NULL BLOB.
		return true;
	}

	// Got a file's name on the command line, so open it.
	img_name = cmdline.extra_args()[0];
	ifstream img_file(img_name.c_str(), ios::binary);
	if (img_file) {
		// Slurp file contents into RAM with minimum copying.  (Idiom
		// explained here: http://stackoverflow.com/questions/116038/)
		//
		// By loading the file into a C++ string (stringstream::str())
		// and assigning that directly to a mysqlpp::sql_blob, we avoid
		// truncating the binary data at the first null character.
		img.data.data = static_cast<const stringstream*>(
				&(stringstream() << img_file.rdbuf()))->str();

		// Check JPEG data for sanity.
		const char* error;
		if (is_jpeg(img.data.data, &error)) {
			return true;
		}
		else {
			cerr << '"' << img_name << "\" isn't a JPEG: " <<
					error << '!' << endl;
		}
	}

	cmdline.print_usage("[jpeg_file]");
	return false;
}


int
main(int argc, char *argv[])
{
	// Get database access parameters from command line
	mysqlpp::examples::CommandLine cmdline(argc, argv);
	if (!cmdline) {
		return 1;
	}

	try {
		// Establish the connection to the database server.
		mysqlpp::Connection con(mysqlpp::examples::db_name,

				cmdline.server(), cmdline.user(), cmdline.pass());

		// Load the file named on the command line
		images img(mysqlpp::null, mysqlpp::null);
		string img_name("NULL");
		if (load_jpeg_file(cmdline, img, img_name)) {
			// Insert image data or SQL NULL into the images.data BLOB
			// column.  The key here is that we're holding the raw
			// binary data in a mysqlpp::sql_blob, which avoids data
			// conversion problems that can lead to treating BLOB data
			// as C strings, thus causing null-truncation.  The fact
			// that we're using SSQLS here is a side issue, simply
			// demonstrating that mysqlpp::Null<mysqlpp::sql_blob> is
			// now legal in SSQLS, as of MySQL++ 3.0.7.
			Query query = con.query();
			query.insert(img);
			SimpleResult res = query.execute();




			// Report successful insertion
			cout << "Inserted \"" << img_name <<
					"\" into images table, " << img.data.data.size() <<
					" bytes, ID " << res.insert_id() << endl;
		}
	}
	catch (const BadQuery& er) {
		// Handle any query errors
		cerr << "Query error: " << er.what() << endl;
		return -1;
	}
	catch (const BadConversion& er) {
		// Handle bad conversions
		cerr << "Conversion error: " << er.what() << endl <<
				"\tretrieved data size: " << er.retrieved <<
				", actual size: " << er.actual_size << endl;
		return -1;
	}

	catch (const Exception& er) {
		// Catch-all for any other MySQL++ exceptions
		cerr << "Error: " << er.what() << endl;
		return -1;
	}

	return 0;
}

Changes to examples/simple2.cpp.

1

2
3
4


5




6


7

8


9

10
11
12

13
14
15

16






17
18












19
20


21
22
23
24
25

26
27
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
56
57










58
59
60


61
62
63









64
65
66
67
68
69
70
71
72



73







74
75
76
77

78



79



80



81


82

83
84
85


86









/***********************************************************************

 simple2.cpp - Retrieves the entire contents of the sample stock table
	using a "store" query, and prints it out.



 Copyright (c) 1998 by Kevin Atkinson, (c) 1999-2001 by MySQL AB, and




 (c) 2004-2009 by Educational Technology Resources, Inc.  Others may


 also hold copyrights on code in this file.  See the CREDITS.txt file

 in the top directory of the distribution for details.




 This file is part of MySQL++.

 MySQL++ is free software; you can redistribute it and/or modify it

 under the terms of the GNU Lesser General Public License as published
 by the Free Software Foundation; either version 2.1 of the License, or
 (at your option) any later version.








 MySQL++ is distributed in the hope that it will be useful, but WITHOUT
 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or












 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
 License for more details.



 You should have received a copy of the GNU Lesser General Public
 License along with MySQL++; if not, write to the Free Software
 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
 USA

***********************************************************************/

#include "cmdline.h"




#include "printdata.h"










#include <mysql++.h>












#include <iostream>
#include <iomanip>

using namespace std;


int
main(int argc, char *argv[])










{
	// Get database access parameters from command line
	mysqlpp::examples::CommandLine cmdline(argc, argv);
	if (!cmdline) {
		return 1;


	}



	// Connect to the sample database.





	mysqlpp::Connection conn(false);
	if (conn.connect(mysqlpp::examples::db_name, cmdline.server(),


			cmdline.user(), cmdline.pass())) {
		// Retrieve the sample stock table set up by resetdb


		mysqlpp::Query query = conn.query("select * from stock");





		mysqlpp::StoreQueryResult res = query.store();





		// Display results
		if (res) {
			// Display header










			cout.setf(ios::left);
			cout << setw(31) << "Item" <<
					setw(10) << "Num" <<


					setw(10) << "Weight" <<
					setw(10) << "Price" <<
					"Date" << endl << endl;










			// Get each row in result set, and print its contents
			for (size_t i = 0; i < res.num_rows(); ++i) {
				cout << setw(30) << res[i]["item"] << ' ' <<
						setw(9) << res[i]["num"] << ' ' <<
						setw(9) << res[i]["weight"] << ' ' <<
						setw(9) << res[i]["price"] << ' ' <<
						setw(9) << res[i]["sdate"] <<
						endl;



			}







		}
		else {
			cerr << "Failed to get stock table: " << query.error() << endl;
			return 1;

		}







		return 0;



	}


	else {

		cerr << "DB connection failed: " << conn.error() << endl;
		return 1;
	}


}









<
>
|
|

>
>
|
>
>
>
>
|
>
>
|
>
|
>
>

>
|

|
>
|
|
|
>

>
>
>
>
>
>
|
|
>
>
>
>
>
>
>
>
>
>
>
>
|
|
>
>

<
<
|
<
>
|

|
>
>
>
>
|
>
>

>
>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>

<
<

|
>

<
<
>
>
>
>
>
>
>
>
>
>
|
<
<
<
<
>
>
|
>
>

|
>
>
>
>
>
|
|
>
>
|
|
>
>
|
>
>
>
>
>
|
>
>
>
>

|
<
<
>
>
>
>
>
>
>
>
>
>
|
|
|
>
>
|
<
<
>
>
>
>
>
>
>
>
>

<
<
<
|
|
|
|
|
>
>
>
|
>
>
>
>
>
>
>
|
<
<
<
>
|
>
>
>

>
>
>
|
>
>
>
|
>
>
|
>
|
<
|
>
>
|
>
>
>
>
>
>
>
>
>

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
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


56

57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88


89
90
91
92


93
94
95
96
97
98
99
100
101
102
103




104
105
106
107
108
109
110
111
112
113
114
115
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
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
191
192
193
194
195
196
197
198

199
200
201
202
203
204
205
206
207
208
209
210
211

<?xml version="1.0" encoding='UTF-8'?>
<!DOCTYPE sect1 PUBLIC "-//OASIS//DTD DocBook V4.2//EN"
    "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">

<sect1 id="overview">
  <title>Overview</title>

  <para>MySQL++ has a lot of complexity and power to cope with the
  variety of ways people use databases, but at bottom it doesn&#x2019;t
  work all that differently than other database access APIs. The usage
  pattern looks like this:</para>

  <orderedlist>
    <listitem><para>Open the connection</para></listitem>

    <listitem><para>Form and execute the query</para></listitem>

    <listitem><para>If successful, iterate through the result
    set</para></listitem>

    <listitem><para>Else, deal with errors</para></listitem>
  </orderedlist>

  <para>Each of these steps corresponds to a MySQL++ class or class
  hierarchy. An overview of each follows.</para>


  <sect2 id="Connection">
    <title>The Connection Object</title>

    <para>A <ulink type="classref" url="Connection"/> object manages the
    connection to the MySQL server. You need at least one of these
    objects to do anything. Because the other MySQL++ objects your
    program will use often depend (at least indirectly) on the
    <classname>Connection</classname> instance, the
    <classname>Connection</classname> object needs to live at least as
    long as all other MySQL++ objects in your program.</para>

    <para>MySQL supports many different types of data connection between
    the client and the server: TCP/IP, Unix domain sockets, and Windows
    named pipes. The generic <classname>Connection</classname> class
    supports all of these, figuring out which one you mean based on the
    parameters you pass to
    <methodname>Connection::connect()</methodname>. But if you know in
    advance that your program only needs one particular connection type,
    there are subclasses with simpler interfaces. For example,
    there&#x2019;s <ulink type="classref" url="TCPConnection"/> if you
    know your program will always use a networked database
    server.</para>
  </sect2>


  <sect2 id="Query">
    <title>The Query Object</title>



    <para>Most often, you create SQL queries using a <ulink

    type="classref" url="Query"/> object created by the
    <classname>Connection</classname> object.</para>

    <para><classname>Query</classname> acts as a standard C++ output
    stream, so you can write data to it like you would to
    <classname>std::cout</classname> or
    <classname>std::ostringstream</classname>. This is the most C++ish
    way MySQL++ provides for building up a query string.  The library
    includes <ulink url="../refman/manip_8h.html">stream
    manipulators</ulink> that are type-aware so it&#x2019;s easy to build
    up syntactically-correct SQL.</para>

    <para><classname>Query</classname> also has a feature called <xref
    linkend="tquery"/> which work something like C&#x2019;s
    <function>printf()</function> function: you set up a fixed query
    string with tags inside that indicate where to insert the variable
    parts. If you have multiple queries that are structurally similar,
    you simply set up one template query, and use that in the various
    locations of your program.</para>

    <para>A third method for building queries is to use
    <classname>Query</classname> with <link
    linkend="ssqls">SSQLS</link>. This feature lets you create C++
    structures that mirror your database schemas. These in turn give
    <classname>Query</classname> the information it needs to build many
    common SQL queries for you. It can <command>INSERT</command>,
    <command>REPLACE</command> and <command>UPDATE</command> rows in a
    table given the data in SSQLS form. It can also generate
    <command>SELECT * FROM SomeTable</command> queries and store the
    results as an STL collection of SSQLSes.</para>
  </sect2>




  <sect2 id="Result">
    <title>Result Sets</title>



    <para>The field data in a result set are stored in a special
    <classname>std::string</classname>-like class called <ulink
    type="classref" url="String"/>. This class has conversion operators
    that let you automatically convert these objects to any of the basic
    C data types. Additionally, MySQL++ defines classes like <ulink
    type="structref" url="DateTime"/>, which you can initialize from a
    MySQL <command>DATETIME</command> string. These automatic
    conversions are protected against bad conversions, and can either
    set a warning flag or throw an exception, depending on how you set
    the library up.</para>





    <para>As for the result sets as a whole, MySQL++ has a number of
    different ways of representing them:</para>

    <sect3 id="SimpleResult">
      <title>Queries That Do Not Return Data</title>

      <para>Not all SQL queries return data. An example is
      <command>CREATE TABLE</command>. For these types of queries, there
      is a special result type (<ulink type="classref"
      url="SimpleResult"/>) that simply reports the state resulting from
      the query: whether the query was successful, how many rows it
      impacted (if any), etc.</para>
    </sect3>

    <sect3 id="StoreQueryResult">
      <title>Queries That Return Data: MySQL++ Data Structures</title>

      <para>The most direct way to retrieve a result set is to use
      <methodname>Query::store()</methodname>. This returns a <ulink
      type="classref" url="StoreQueryResult"/> object, which derives
      from <classname>std::vector&lt;mysqlpp::Row&gt;</classname>,
      making it a random-access container of <ulink type="classref"
      url="Row"/>s. In turn, each <classname>Row</classname> object is
      like a <classname>std::vector</classname> of
      <classname>String</classname> objects, one for each field in the
      result set. Therefore, you can treat
      <classname>StoreQueryResult</classname> as a two-dimensional
      array: you can get the 5th field on the 2nd row by simply saying
      <methodname>result[1][4]</methodname>. You can also access row
      elements by field name, like this:
      <methodname>result[2]["price"]</methodname>.</para>

      <para>A less direct way of working with query results is to use


      <methodname>Query::use()</methodname>, which returns a <ulink
      type="classref" url="UseQueryResult"/> object. This class acts
      like an STL input iterator rather than a
      <classname>std::vector</classname>: you walk through your result
      set processing one row at a time, always going forward. You
      can&#x2019;t seek around in the result set, and you can&#x2019;t
      know how many results are in the set until you find the end. In
      payment for that inconvenience, you get better memory efficiency,
      because the entire result set doesn&#x2019;t need to be stored in
      RAM. This is very useful when you need large result sets.</para>
    </sect3>

    <sect3 id="storein">
      <title>Queries That Return Data: Specialized SQL
      Structures</title>



      <para>Accessing results through MySQL++&#x2019;s data structures is
      a pretty low level of abstraction. It&#x2019;s better than using
      the MySQL C API, but not by much. You can elevate things a little
      closer to the level of the problem space by using the <link
      linkend="ssqls">SSQLS feature</link>. This lets you define C++
      structures that match the table structures in your database
      schema. In addition, it&#x2019;s easy to use SSQLSes with regular
      STL containers (and thus, algorithms) so you don&#x2019;t have to
      deal with the quirks of MySQL++&#x2019;s data structures.</para>




      <para>The advantage of this method is that your program will
      require very little embedded SQL code. You can simply execute a
      query, and receive your results as C++ data structures, which can
      be accessed just as you would any other structure. The results can
      be accessed through the Row object, or you can ask the library to
      dump the results into an STL container &mdash; sequential or
      set-associative, it doesn&#x2019;t matter &mdash; for you. Consider
      this:</para>

      <programlisting>
vector&lt;stock&gt; v;
query &lt;&lt; "SELECT * FROM stock";
query.storein(v);
for (vector&lt;stock&gt;::iterator it = v.begin(); it != v.end(); ++it) {
  cout &lt;&lt; "Price: " &lt;&lt; it-&gt;price &lt;&lt; endl;
}</programlisting>




      <para>Isn&#x2019;t that slick?</para>

      <para>If you don&#x2019;t want to create SSQLSes to match your
      table structures, as of MySQL++ v3 you can now use
      <classname>Row</classname> here instead:</para>

      <programlisting>
vector&lt;mysqlpp::Row&gt; v;
query &lt;&lt; "SELECT * FROM stock";
query.storein(v);
for (vector&lt;mysqlpp::Row&gt;::iterator it = v.begin(); it != v.end(); ++it) {
  cout &lt;&lt; "Price: " &lt;&lt; it->at("price") &lt;&lt; endl;
}</programlisting>

      <para>It lacks a certain syntactic elegance, but it has its
      uses.</para>
    </sect3>
  </sect2>



  <sect2 id="exceptions-intro">
    <title>Exceptions</title>

    <para>By default, the library throws <xref linkend="exceptions"/>
    whenever it encounters an error. You can ask the library to set
    an error flag instead, if you like, but the exceptions carry more
    information. Not only do they include a string member telling you
    why the exception was thrown, there are several exception types,
    so you can distinguish between different error types within a
    single <symbol>try</symbol> block.</para>
  </sect2>
</sect1>

Changes to examples/simple3.cpp.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
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
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
/***********************************************************************
 simple3.cpp - Example showing how to use the 'use' method of retrieving
	a table, as opposed to the more common 'store' method illustrated
	by the simple2 example.

 Copyright (c) 2005-2009 by Educational Technology Resources, Inc.
 Others may also hold copyrights on code in this file.  See the CREDITS
 file in the top directory of the distribution for details.

 This file is part of MySQL++.

 MySQL++ is free software; you can redistribute it and/or modify it
 under the terms of the GNU Lesser General Public License as published
 by the Free Software Foundation; either version 2.1 of the License, or
 (at your option) any later version.

 MySQL++ is distributed in the hope that it will be useful, but WITHOUT
 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
 License for more details.

 You should have received a copy of the GNU Lesser General Public
 License along with MySQL++; if not, write to the Free Software
 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
 USA
***********************************************************************/

#include "cmdline.h"
#include "printdata.h"

#include <mysql++.h>

#include <iostream>
#include <iomanip>

using namespace std;

int
main(int argc, char *argv[])
{
	// Get database access parameters from command line
	mysqlpp::examples::CommandLine cmdline(argc, argv);
	if (!cmdline) {
		return 1;
	}

	// Connect to the sample database.
	mysqlpp::Connection conn(false);
	if (conn.connect(mysqlpp::examples::db_name, cmdline.server(),
			cmdline.user(), cmdline.pass())) {
		// Ask for all rows from the sample stock table and display
		// them.  Unlike simple2 example, we retreive each row one at
		// a time instead of storing the entire result set in memory
		// and then iterating over it.
		mysqlpp::Query query = conn.query("select * from stock");
		if (mysqlpp::UseQueryResult res = query.use()) {
			// Display header
			cout.setf(ios::left);
			cout << setw(31) << "Item" <<
					setw(10) << "Num" <<
					setw(10) << "Weight" <<
					setw(10) << "Price" <<
					"Date" << endl << endl;

			// Get each row in result set, and print its contents
			while (mysqlpp::Row row = res.fetch_row()) {
				cout << setw(30) << row["item"] << ' ' <<
						setw(9) << row["num"] << ' ' <<
						setw(9) << row["weight"] << ' ' <<
						setw(9) << row["price"] << ' ' <<
						setw(9) << row["sdate"] <<
						endl;
			}

			// Check for error: can't distinguish "end of results" and
			// error cases in return from fetch_row() otherwise.
			if (conn.errnum()) {
				cerr << "Error received in fetching a row: " <<
						conn.error() << endl;
				return 1;
			}
			return 0;
		}
		else {
			cerr << "Failed to get stock item: " << query.error() << endl;
			return 1;
		}
	}
	else {
		cerr << "DB connection failed: " << conn.error() << endl;
		return 1;
	}
}

|
<
<

|
|
|



















|
<

<
<
<
<
<
|
|
<
<
<
<
<
<
<
<
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
|
<
<
<
<
<
<
<
<
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
1
2


3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26

27





28
29








30

















31








32




















/***********************************************************************
 null.cpp - Defines a few things declared in null.h



 Copyright (c) 2007 by Educational Technology Resources, Inc.
 Others may also hold copyrights on code in this file.  See the
 CREDITS.txt file in the top directory of the distribution for details.

 This file is part of MySQL++.

 MySQL++ is free software; you can redistribute it and/or modify it
 under the terms of the GNU Lesser General Public License as published
 by the Free Software Foundation; either version 2.1 of the License, or
 (at your option) any later version.

 MySQL++ is distributed in the hope that it will be useful, but WITHOUT
 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
 License for more details.

 You should have received a copy of the GNU Lesser General Public
 License along with MySQL++; if not, write to the Free Software
 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
 USA
***********************************************************************/

#include "null.h"







namespace mysqlpp {
	/// \brief "NULL" string constant used in many places within MySQL++








	const std::string null_str("NULL");

















}





























Changes to examples/ssqls1.cpp.

1
2
3
4
5
6
7
8
9
10
11
12
/***********************************************************************
 ssqls1.cpp - Example that produces the same results as simple1, but it
	uses a Specialized SQL Structure to store the results instead of a
	MySQL++ Result object.
 
 Copyright (c) 1998 by Kevin Atkinson, (c) 1999-2001 by MySQL AB, and
 (c) 2004-2009 by Educational Technology Resources, Inc.  Others may
 also hold copyrights on code in this file.  See the CREDITS.txt file
 in the top directory of the distribution for details.

 This file is part of MySQL++.


|
|
<
|







1
2
3

4
5
6
7
8
9
10
11
/***********************************************************************
 tquery1.cpp - Example similar to ssqls3.cpp, except that it uses
	template queries instead of SSQLS.


 Copyright (c) 1998 by Kevin Atkinson, (c) 1999-2001 by MySQL AB, and
 (c) 2004-2009 by Educational Technology Resources, Inc.  Others may
 also hold copyrights on code in this file.  See the CREDITS.txt file
 in the top directory of the distribution for details.

 This file is part of MySQL++.

24
25
26
27
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
56
57
58
59

60

61
62
63
64
65
66

67
68







69


70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
 License along with MySQL++; if not, write to the Free Software
 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
 USA
***********************************************************************/

#include "cmdline.h"
#include "printdata.h"
#include "stock.h"

#include <iostream>
#include <vector>

using namespace std;

int
main(int argc, char *argv[])
{
	// Get database access parameters from command line
	mysqlpp::examples::CommandLine cmdline(argc, argv);
	if (!cmdline) {
		return 1;
	}

	try {						
		// Establish the connection to the database server.
		mysqlpp::Connection con(mysqlpp::examples::db_name,
				cmdline.server(), cmdline.user(), cmdline.pass());

		// Retrieve a subset of the stock table's columns, and store
		// the data in a vector of 'stock' SSQLS structures.  See the
		// user manual for the consequences arising from this quiet
		// ability to store a subset of the table in the stock SSQLS.
		mysqlpp::Query query = con.query("select item,description from stock");
		vector<stock> res;
		query.storein(res);


		// Display the items

		cout << "We have:" << endl;
		vector<stock>::iterator it;
		for (it = res.begin(); it != res.end(); ++it) {
			cout << '\t' << it->item;
			if (it->description != mysqlpp::null) {
				cout << " (" << it->description << ")";

			}
			cout << endl;







		}


	}
	catch (const mysqlpp::BadQuery& er) {
		// Handle any query errors
		cerr << "Query error: " << er.what() << endl;
		return -1;
	}
	catch (const mysqlpp::BadConversion& er) {
		// Handle bad conversions; e.g. type mismatch populating 'stock'
		cerr << "Conversion error: " << er.what() << endl <<
				"\tretrieved data size: " << er.retrieved <<
				", actual size: " << er.actual_size << endl;
		return -1;
	}
	catch (const mysqlpp::Exception& er) {
		// Catch-all for any other MySQL++ exceptions
		cerr << "Error: " << er.what() << endl;
		return -1;
	}

	return 0;
}







<


<












|




|
|
<
<
|
|
|

>
|
>
|
<
<
<
|
<
>
|
|
>
>
>
>
>
>
>
|
>
>







|













23
24
25
26
27
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
56
57
58



59

60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
 License along with MySQL++; if not, write to the Free Software
 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
 USA
***********************************************************************/

#include "cmdline.h"
#include "printdata.h"


#include <iostream>


using namespace std;

int
main(int argc, char *argv[])
{
	// Get database access parameters from command line
	mysqlpp::examples::CommandLine cmdline(argc, argv);
	if (!cmdline) {
		return 1;
	}

	try {
		// Establish the connection to the database server.
		mysqlpp::Connection con(mysqlpp::examples::db_name,
				cmdline.server(), cmdline.user(), cmdline.pass());

		// Build a template query to retrieve a stock item given by
		// item name.


		mysqlpp::Query query = con.query(
				"select * from stock where item = %0q");
		query.parse();

		// Retrieve an item added by resetdb; it won't be there if
		// tquery* or ssqls3 is run since resetdb.
		mysqlpp::StoreQueryResult res1 = query.store("Nürnberger Brats");
		if (res1.empty()) {



			throw mysqlpp::BadQuery("UTF-8 bratwurst item not found in "

					"table, run resetdb");
		}

		// Replace the proper German name with a 7-bit ASCII
		// approximation using a different template query.
		query.reset();		// forget previous template query data
		query << "update stock set item = %0q where item = %1q";
		query.parse();
		mysqlpp::SimpleResult res2 = query.execute("Nuerenberger Bratwurst",
				res1[0][0].c_str());

		// Print the new table contents.
		print_stock_table(query);
	}
	catch (const mysqlpp::BadQuery& er) {
		// Handle any query errors
		cerr << "Query error: " << er.what() << endl;
		return -1;
	}
	catch (const mysqlpp::BadConversion& er) {
		// Handle bad conversions
		cerr << "Conversion error: " << er.what() << endl <<
				"\tretrieved data size: " << er.retrieved <<
				", actual size: " << er.actual_size << endl;
		return -1;
	}
	catch (const mysqlpp::Exception& er) {
		// Catch-all for any other MySQL++ exceptions
		cerr << "Error: " << er.what() << endl;
		return -1;
	}

	return 0;
}

Changes to examples/ssqls2.cpp.

1
2
3



4
5
6
7
8
9
10
/***********************************************************************
 ssqls2.cpp - Example showing how to insert a row using the Specialized
	SQL Structures feature of MySQL++.




 Copyright (c) 1998 by Kevin Atkinson, (c) 1999-2001 by MySQL AB, and
 (c) 2004-2009 by Educational Technology Resources, Inc.  Others may
 also hold copyrights on code in this file.  See the CREDITS.txt file
 in the top directory of the distribution for details.

 This file is part of MySQL++.

|
|
>
>
>







1
2
3
4
5
6
7
8
9
10
11
12
13
/***********************************************************************
 tquery2.cpp - Same as tquery1.cpp, except that it passes the template
	query parameters in a SQLQueryParms object, instead of separately.
	This is useful when the calling code doesn't know in advance how
	many parameters there will be.  This is most likely because the
	templates are coming from somewhere else, or being generated.

 Copyright (c) 1998 by Kevin Atkinson, (c) 1999-2001 by MySQL AB, and
 (c) 2004-2009 by Educational Technology Resources, Inc.  Others may
 also hold copyrights on code in this file.  See the CREDITS.txt file
 in the top directory of the distribution for details.

 This file is part of MySQL++.
23
24
25
26
27
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
56
57
58
59

60
61

62
63





64
65




66


67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
 License along with MySQL++; if not, write to the Free Software
 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
 USA
***********************************************************************/

#include "cmdline.h"
#include "printdata.h"
#include "stock.h"

#include <iostream>
#include <limits>

using namespace std;

int
main(int argc, char *argv[])
{
	// Get database access parameters from command line
	mysqlpp::examples::CommandLine cmdline(argc, argv);
	if (!cmdline) {
		return 1;
	}

	try {
		// Establish the connection to the database server.
		mysqlpp::Connection con(mysqlpp::examples::db_name,
				cmdline.server(), cmdline.user(), cmdline.pass());

		// Create and populate a stock object.  We could also have used
		// the set() member, which takes the same parameters as this
		// constructor.
		stock row("Hot Dogs", 100, 1.5,
				numeric_limits<double>::infinity(),	// "priceless," ha!
				mysqlpp::sql_date("1998-09-25"), mysqlpp::null);

		// Form the query to insert the row into the stock table.
		mysqlpp::Query query = con.query();

		query.insert(row);


		// Show the query about to be executed.
		cout << "Query: " << query << endl;






		// Execute the query.  We use execute() because INSERT doesn't




		// return a result set.


		query.execute();

		// Retrieve and print out the new table contents.
		print_stock_table(query);
	}
	catch (const mysqlpp::BadQuery& er) {
		// Handle any query errors
		cerr << "Query error: " << er.what() << endl;
		return -1;
	}
	catch (const mysqlpp::BadConversion& er) {	
		// Handle bad conversions
		cerr << "Conversion error: " << er.what() << endl <<
				"\tretrieved data size: " << er.retrieved <<
				", actual size: " << er.actual_size << endl;
		return -1;
	}
	catch (const mysqlpp::Exception& er) {







<


<

















<
<
<
|
<
<
|
<
|
>
|

>
|
|
>
>
>
>
>
|
|
>
>
>
>
|
>
>
|

|







|







26
27
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
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
 License along with MySQL++; if not, write to the Free Software
 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
 USA
***********************************************************************/

#include "cmdline.h"
#include "printdata.h"


#include <iostream>


using namespace std;

int
main(int argc, char *argv[])
{
	// Get database access parameters from command line
	mysqlpp::examples::CommandLine cmdline(argc, argv);
	if (!cmdline) {
		return 1;
	}

	try {
		// Establish the connection to the database server.
		mysqlpp::Connection con(mysqlpp::examples::db_name,
				cmdline.server(), cmdline.user(), cmdline.pass());




		// Build a template query to retrieve a stock item given by


		// item name.

		mysqlpp::Query query = con.query(
				"select * from stock where item = %0q");
		query.parse();

		// Retrieve an item added by resetdb; it won't be there if
		// tquery* or ssqls3 is run since resetdb.
		mysqlpp::SQLQueryParms sqp;
		sqp << "Nürnberger Brats";
		mysqlpp::StoreQueryResult res1 = query.store(sqp);
		if (res1.empty()) {
			throw mysqlpp::BadQuery("UTF-8 bratwurst item not found in "
					"table, run resetdb");
		}

		// Replace the proper German name with a 7-bit ASCII
		// approximation using a different template query.
		query.reset();		// forget previous template query info
		query << "update stock set item = %0q where item = %1q";
		query.parse();
		sqp.clear();
		sqp << "Nuerenberger Bratwurst" << res1[0][0].c_str();
		mysqlpp::SimpleResult res2 = query.execute(sqp);

		// Print the new table contents.
		print_stock_table(query);
	}
	catch (const mysqlpp::BadQuery& er) {
		// Handle any query errors
		cerr << "Query error: " << er.what() << endl;
		return -1;
	}
	catch (const mysqlpp::BadConversion& er) {
		// Handle bad conversions
		cerr << "Conversion error: " << er.what() << endl <<
				"\tretrieved data size: " << er.retrieved <<
				", actual size: " << er.actual_size << endl;
		return -1;
	}
	catch (const mysqlpp::Exception& er) {

Changes to examples/ssqls3.cpp.

1
2
3




4
5
6
7
8
9
10
/***********************************************************************
 ssqls3.cpp - Example showing how to update an SQL row using the
	Specialized SQL Structures feature of MySQL++.





 Copyright (c) 1998 by Kevin Atkinson, (c) 1999-2001 by MySQL AB, and
 (c) 2004-2009 by Educational Technology Resources, Inc.  Others may
 also hold copyrights on code in this file.  See the CREDITS.txt file
 in the top directory of the distribution for details.

 This file is part of MySQL++.

|
|
>
>
>
>







1
2
3
4
5
6
7
8
9
10
11
12
13
14
/***********************************************************************
 tquery3.cpp - Similar to tquery1.cpp but uses unquoted parameters.
	It's here more for code test coverage than because it shows
	something interesting.  We've historically had a problem with
	tqueries with just one parameter; we cover the quoted case in
	resetdb and the other tquery examples, so we get the unquoted
	one here.

 Copyright (c) 1998 by Kevin Atkinson, (c) 1999-2001 by MySQL AB, and
 (c) 2004-2009 by Educational Technology Resources, Inc.  Others may
 also hold copyrights on code in this file.  See the CREDITS.txt file
 in the top directory of the distribution for details.

 This file is part of MySQL++.
23
24
25
26
27
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

56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
 License along with MySQL++; if not, write to the Free Software
 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
 USA
***********************************************************************/

#include "cmdline.h"
#include "printdata.h"
#include "stock.h"

#include <iostream>

using namespace std;

int
main(int argc, char *argv[])
{
	// Get database access parameters from command line
	mysqlpp::examples::CommandLine cmdline(argc, argv);
	if (!cmdline) {
		return 1;
	}

	try {
		// Establish the connection to the database server.
		mysqlpp::Connection con(mysqlpp::examples::db_name,
				cmdline.server(), cmdline.user(), cmdline.pass());

		// Build a query to retrieve the stock item that has Unicode
		// characters encoded in UTF-8 form.
		mysqlpp::Query query = con.query("select * from stock ");

		query << "where item = " << mysqlpp::quote << "Nürnberger Brats";

		// Retrieve the row, throwing an exception if it fails.

		mysqlpp::StoreQueryResult res = query.store();
		if (res.empty()) {
			throw mysqlpp::BadQuery("UTF-8 bratwurst item not found in "
					"table, run resetdb");
		}

		// Because there should only be one row in the result set,
		// there's no point in storing the result in an STL container.
		// We can store the first row directly into a stock structure
		// because one of an SSQLS's constructors takes a Row object.
		stock row = res[0];

		// Create a copy so that the replace query knows what the
		// original values are.
		stock orig_row = row;

		// Change the stock object's item to use only 7-bit ASCII, and
		// to deliberately be wider than normal column widths printed
		// by print_stock_table().
		row.item = "Nuerenberger Bratwurst";

		// Form the query to replace the row in the stock table.
		query.update(orig_row, row);

		// Show the query about to be executed.
		cout << "Query: " << query << endl;

		// Run the query with execute(), since UPDATE doesn't return a
		// result set.
		query.execute();

		// Retrieve and print out the new table contents.
		print_stock_table(query);
	}
	catch (const mysqlpp::BadQuery& er) {
		// Handle any query errors
		cerr << "Query error: " << er.what() << endl;
		return -1;
	}
	catch (const mysqlpp::BadConversion& er) {
		// Handle bad conversions
		cerr << "Conversion error: " << er.what() << endl <<
				"\tretrieved data size: " << er.retrieved <<
				", actual size: " << er.actual_size << endl;
		return -1;
	}
	catch (const mysqlpp::Exception& er) {
		// Catch-all for any other MySQL++ exceptions
		cerr << "Error: " << er.what() << endl;
		return -1;
	}

	return 0;
}







<



















|
|
|
>
|

<
>
|
<
|
<
<
|
<
<
<
<
<
|
<
<
<
|
<
<
<
<
|
<
<
|
<
|
|
<
<
<
|
<
<




|
<
<
<
<
<
<
<




|




27
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
56
57
58

59
60

61


62





63



64




65


66

67
68



69


70
71
72
73
74







75
76
77
78
79
80
81
82
83
 License along with MySQL++; if not, write to the Free Software
 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
 USA
***********************************************************************/

#include "cmdline.h"
#include "printdata.h"


#include <iostream>

using namespace std;

int
main(int argc, char *argv[])
{
	// Get database access parameters from command line
	mysqlpp::examples::CommandLine cmdline(argc, argv);
	if (!cmdline) {
		return 1;
	}

	try {
		// Establish the connection to the database server.
		mysqlpp::Connection con(mysqlpp::examples::db_name,
				cmdline.server(), cmdline.user(), cmdline.pass());

		// Build a template query to retrieve item names for stock
		// entries with a quantity over some threshold.
		mysqlpp::Query query = con.query(
				"select item from stock where num > %0");
		query.parse();


		// Get a list of things we have lots of in stock
		if (mysqlpp::StoreQueryResult res = query.store(80)) {

			cout << "Stuff we have a lot of in stock:" << endl;


			for (size_t i = 0; i < res.num_rows(); ++i) {





				cout << '\t' << res[i]["item"] << endl;



			}




		}


		else {

			cerr << "Failed to get item list: " << query.error() << endl;
			return 1;



		}


	}
	catch (const mysqlpp::BadQuery& er) {
		// Handle any query errors
		cerr << "Query error: " << er.what() << endl;
		return 2;







	}
	catch (const mysqlpp::Exception& er) {
		// Catch-all for any other MySQL++ exceptions
		cerr << "Error: " << er.what() << endl;
		return 2;
	}

	return 0;
}

Changes to examples/ssqls4.cpp.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/***********************************************************************
 ssqls4.cpp - Example very similar to ssqls1.cpp, except that it
	stores its result set in an STL set container.  This demonstrates
	how one can manipulate MySQL++ result sets in a very natural C++
	style.

 Copyright (c) 1998 by Kevin Atkinson, (c) 1999-2001 by MySQL AB, and
 (c) 2004-2010 by Educational Technology Resources, Inc.  Others may
 also hold copyrights on code in this file.  See the CREDITS.txt file
 in the top directory of the distribution for details.

 This file is part of MySQL++.

 MySQL++ is free software; you can redistribute it and/or modify it
 under the terms of the GNU Lesser General Public License as published

|
<
<
|


|







1
2


3
4
5
6
7
8
9
10
11
12
13
/***********************************************************************
 transaction.cpp - Example showing how to use MySQL++'s transaction


 	features.

 Copyright (c) 1998 by Kevin Atkinson, (c) 1999-2001 by MySQL AB, and
 (c) 2004-2009 by Educational Technology Resources, Inc.  Others may
 also hold copyrights on code in this file.  See the CREDITS.txt file
 in the top directory of the distribution for details.

 This file is part of MySQL++.

 MySQL++ is free software; you can redistribute it and/or modify it
 under the terms of the GNU Lesser General Public License as published
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
56

57
58

59

60
61
62
63
64


65
66
67


68
69




70
71

72
73

74





75
76




77

78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
***********************************************************************/

#include "cmdline.h"
#include "printdata.h"
#include "stock.h"

#include <iostream>


using namespace std;

int
main(int argc, char *argv[])
{
	// Get database access parameters from command line
	mysqlpp::examples::CommandLine cmdline(argc, argv);
	if (!cmdline) {
		return 1;
	}

	try {
		// Establish the connection to the database server.
		mysqlpp::Connection con(mysqlpp::examples::db_name,
				cmdline.server(), cmdline.user(), cmdline.pass());

		// Retrieve all rows from the stock table and put them in an
		// STL set.  Notice that this works just as well as storing them
		// in a vector, which we did in ssqls1.cpp.  It works because
		// SSQLS objects are less-than comparable.
		mysqlpp::Query query = con.query("select * from stock");

		set<stock> res;
		query.storein(res);



		// Display the result set.  Since it is an STL set and we set up
		// the SSQLS to compare based on the item column, the rows will
		// be sorted by item.
		print_stock_header(res.size());
		set<stock>::iterator it;


		cout.precision(3);
		for (it = res.begin(); it != res.end(); ++it) {
			print_stock_row(it->item.c_str(), it->num, it->weight,


					it->price, it->sDate);
		}





		// Use set's find method to look up a stock item by item name.

		// This also uses the SSQLS comparison setup.
		it = res.find(stock("Hotdog Buns"));

		if (it != res.end()) {





			cout << endl << "Currently " << it->num <<
					" hotdog buns in stock." << endl;




		}

		else {
			cout << endl << "Sorry, no hotdog buns in stock." << endl;
		}
	}
	catch (const mysqlpp::BadQuery& er) {
		// Handle any query errors
		cerr << "Query error: " << er.what() << endl;
		return -1;
	}
	catch (const mysqlpp::BadConversion& er) {
		// Handle bad conversions
		cerr << "Conversion error: " << er.what() << endl <<
				"\tretrieved data size: " << er.retrieved <<
				", actual size: " << er.actual_size << endl;
		return -1;
	}
	catch (const mysqlpp::Exception& er) {







>

















<
<
<
|
|
>
|
|
>
|
>
|
|
|
|
|
>
>
|
|
|
>
>
|
|
>
>
>
>

<
>
|
|
>
|
>
>
>
>
>
|
|
>
>
>
>

>
|
|
|






|







26
27
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
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77

78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
***********************************************************************/

#include "cmdline.h"
#include "printdata.h"
#include "stock.h"

#include <iostream>
#include <cstdio>

using namespace std;

int
main(int argc, char *argv[])
{
	// Get database access parameters from command line
	mysqlpp::examples::CommandLine cmdline(argc, argv);
	if (!cmdline) {
		return 1;
	}

	try {
		// Establish the connection to the database server.
		mysqlpp::Connection con(mysqlpp::examples::db_name,
				cmdline.server(), cmdline.user(), cmdline.pass());




		// Show initial state
		mysqlpp::Query query = con.query();
		cout << "Initial state of stock table:" << endl;
		print_stock_table(query);

		// Insert a few rows in a single transaction set
		{
			// Use a higher level of transaction isolation than MySQL
			// offers by default.  This trades some speed for more
			// predictable behavior.  We've set it to affect all
			// transactions started through this DB server connection,
			// so it affects the next block, too, even if we don't
			// commit this one.
			mysqlpp::Transaction trans(con,
					mysqlpp::Transaction::serializable,
					mysqlpp::Transaction::session);

			stock row("Sauerkraut", 42, 1.2, 0.75,
					mysqlpp::sql_date("2006-03-06"), mysqlpp::null);
			query.insert(row);
			query.execute();

			cout << "\nRow inserted, but not committed." << endl;
			cout << "Verify this with another program (e.g. simple1), "
					"then hit Enter." << endl;
			getchar();


			cout << "\nCommitting transaction gives us:" << endl;
			trans.commit();
			print_stock_table(query);
		}
			
		// Now let's test auto-rollback
		{
			// Start a new transaction, keeping the same isolation level
			// we set above, since it was set to affect the session.
			mysqlpp::Transaction trans(con);
			cout << "\nNow adding catsup to the database..." << endl;

			stock row("Catsup", 3, 3.9, 2.99,
					mysqlpp::sql_date("2006-03-06"), mysqlpp::null);
			query.insert(row);
			query.execute();
		}
		cout << "\nNo, yuck! We don't like catsup. Rolling it back:" <<
				endl;
		print_stock_table(query);
			
	}
	catch (const mysqlpp::BadQuery& er) {
		// Handle any query errors
		cerr << "Query error: " << er.what() << endl;
		return -1;
	}
	catch (const mysqlpp::BadConversion& er) {	
		// Handle bad conversions
		cerr << "Conversion error: " << er.what() << endl <<
				"\tretrieved data size: " << er.retrieved <<
				", actual size: " << er.actual_size << endl;
		return -1;
	}
	catch (const mysqlpp::Exception& er) {

Changes to examples/ssqls5.cpp.



1
2




3

4

5

6


7
8







9




























10

11







12


13


14



15


16



17








18





19
20







21







22







23
24




25




26




27





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

















56

57


58

59



60


61

















































62
63
64

65






66
67

68
69




70
71



72


73
74
75
76
77
78

79



80

81
82



83







84
85









86











































/***********************************************************************
 ssqls5.cpp - Example showing how to use the equal_list() member of




	some SSQLS types to build SELECT queries with custom WHERE clauses.



 Copyright (c) 1998 by Kevin Atkinson, (c) 1999-2001 by MySQL AB, (c)

 2004-2009 by Educational Technology Resources, Inc., and (c) 2005 by


 Chris Frey.  Others may also hold copyrights on code in this file.
 See the CREDITS.txt file in the top directory of the distribution







 for details.






























 This file is part of MySQL++.










 MySQL++ is free software; you can redistribute it and/or modify it


 under the terms of the GNU Lesser General Public License as published



 by the Free Software Foundation; either version 2.1 of the License, or


 (at your option) any later version.












 MySQL++ is distributed in the hope that it will be useful, but WITHOUT





 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public







 License for more details.















 You should have received a copy of the GNU Lesser General Public
 License along with MySQL++; if not, write to the Free Software




 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301




 USA




***********************************************************************/







#include "cmdline.h"





#include "printdata.h"



#include "stock.h"




#include <iostream>
#include <vector>




using namespace std;









int


main(int argc, char *argv[])
{







	// Get database access parameters from command line


	mysqlpp::examples::CommandLine cmdline(argc, argv);






	if (!cmdline) {







		return 1;






	}











	try {

		// Establish the connection to the database server.





		mysqlpp::Connection con(mysqlpp::examples::db_name,


				cmdline.server(), cmdline.user(), cmdline.pass());







		// Get all the rows in the stock table.
		mysqlpp::Query query = con.query("select * from stock");




		vector<stock> res;



		query.storein(res);



















		if (res.size() > 0) {


			// Build a select query using the data from the first row

			// returned by our previous query.



			query << "select * from stock where " <<


					res[0].equal_list(" and ", stock_weight, stock_price);


















































			// Display the finished query.
			cout << "Custom query:\n" << query << endl;

		}






	}
	catch (const mysqlpp::BadQuery& er) {

		// Handle any query errors
		cerr << "Query error: " << er.what() << endl;




		return -1;
	}



	catch (const mysqlpp::BadConversion& er) {


		// Handle bad conversions
		cerr << "Conversion error: " << er.what() << endl <<
				"\tretrieved data size: " << er.retrieved <<
				", actual size: " << er.actual_size << endl;
		return -1;
	}

	catch (const mysqlpp::Exception& er) {



		// Catch-all for any other MySQL++ exceptions

		cerr << "Error: " << er.what() << endl;
		return -1;



	}








	return 0;









}









































>
>
|
|
>
>
>
>
|
>

>
|
>
|
>
>
|
|
>
>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

>
|
>
>
>
>
>
>
>

>
>
|
>
>
|
>
>
>
|
>
>
|
>
>
>

>
>
>
>
>
>
>
>
|
>
>
>
>
>
|
|
>
>
>
>
>
>
>
|
>
>
>
>
>
>
>

>
>
>
>
>
>
>
|
|
>
>
>
>
|
>
>
>
>
|
>
>
>
>
|
>
>
>
>
>

>
|
>
>
>
>
>
|
>
>
>
|
>
>
|
>
|
<

>
>
>
|
>
>
>

>
>
>
>
>
|
>
>
|
|
>
>
>
>
>
>
>
|
>
>
|
>
>
>
>
>
>
|
>
>
>
>
>
>
>
|
>
>
>
>
>
>
|
>
>
>
>
>
>

>
>
>
>
|
>
|
>
>
>
>
>
|
>
>
|
>

>
>
>
>
>
|
|
>
>
>
>
|
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

>
|
>
>
|
>
|
>
>
>
|
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

|
<
>
|
>
>
>
>
>
>
|
<
>
|
<
>
>
>
>
|
|
>
>
>
|
>
>
|
<
<
<
<
|
>
|
>
>
>
|
>
|
<
>
>
>
|
>
>
>
>
>
>
>

|
>
>
>
>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
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
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
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
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
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
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
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
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
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

372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
If you are going to make any changes to MySQL++, this file has some
hints and commentary you may find helpful.


Subversion Access
~~~~~~~~~~~~~~~~~
    To check out the current development version from the Gna!
    Subversion repository, say:

        $ svn co svn://svn.gna.org/svn/mysqlpp/trunk mysqlpp

    If you're a MySQL++ committer, use svn over ssh instead:
    
        $ svn co svn+ssh://LOGIN@svn.gna.org/svn/mysqlpp/trunk mysqlpp

    where LOGIN is your Gna! login name.  You will have to have your
    ssh public key(s) registered with Gna! for this to work.


Bootstrapping the Library
~~~~~~~~~~~~~~~~~~~~~~~~~
    When you check out MySQL++ from svn, there are a lot of things
    "missing" as compared to a distributed tarball, because the
    svn repository contains only source files, no generated files.
    The process that turns a fresh MySQL++ repository checkout into
    something you can build and hack on is called bootstrapping.

    Boostrapping is best done on a modern Unix type platform: Linux, OS
    X, BSD, Solaris...any version released in the last 4 years or so.
    It's possible to do it on Windows, but harder; enough so that we
    cover the options below in a separate section.

    Two of the tools you need to do this are commonly available on
    Unixy systems, at least as an option: Perl 5, and autoconf 1.59
    or higher.  If they're not installed, you can probably run your
    system's package manager to install suitable versions.

    There's a third tool you'll need to bootstrap MySQL++, called
    Bakefile, which you can get from http://bakefile.org/  You will
    need Bakefile 0.2.5 or higher, which in turn requires Python 2.3
    or higher to run.  To build Bakefile from source, you will also
    need SWIG, so if you don't have that, you'll want to use one of
    the binary builds of Bakefile.

    Once you have all the tools in place, you can bootstrap MySQL++
    with a Bourne shell script called bootstrap, which you get as part
    of the svn checkout.  It's fairly powerful, with many options.
    For most cases, it suffices to just run it without any arguments:

        $ ./bootstrap

    For more unusual situations, here's the complete usage:

        $ ./bootstrap [no{doc,ex,lib,opt}] [pedantic] [bat] \
                      [configure flags]

    Arguments:

    nodoc   The documentation won't be considered a prerequisite for
            building the distribution tarball.  This is useful on systems
            where the documentation doesn't build correctly, and you only
            need to make a binary RPM.  That process requires a tarball,
            but doesn't need the documentation.  Don't distribute the
            tarball or SRPM that results, as they are no good for any
            other purpose.

    noex    The generated Makefiles and project files won't try to build
            any of the examples.

    nolib   The generated Makefiles and project files won't try to build
            the MySQL++ library.

    nomaint Turn off "maintainer mode" stuff in the build.  These are
            features used only by those building MySQL++ from svn.  The
            'dist' build target uses this when creating the tarball.

    noopt   Compiler optimization will be turned off.  (This currently
            has no effect on MinGW or Visual C++.)

    pedantic
            Turns on all of GCC's warnings and portability checks.
            Good for checking changes before making a public release.

    bat     Asks cmd.exe to run bootstrap.bat for you.  This is useful
            when using Cygwin just as a command shell in preference
            to cmd.exe, as opposed to using Cygwin to build MySQL++
            using its native tools.  Passing 'bat' stops all command
            line processing in the bootstrap script, so if you
            also pass some of the other options, make 'bat' last.
            The only options that affect the built project files and
            Makefiles work are the no* ones.

    configure options
            As soon as the bootstrap script sees an option that it
            doesn't understand, it stops processing the command line.
            Any subsequent options are passed to the configure script.
            See README-Unix.txt for more on configure script options.


Bootstrapping the Library Using only Windows
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    The thing that makes bootstrapping on Windows difficult is that
    one of the required steps uses a Unix-centric tool, autoconf.
    This section is about working out a way to get that working on
    Windows, or avoiding the need for it, so you can get on with
    hacking on MySQL++ on Windows.

    The thing autoconf does that's relevant to Windows builds
    of MySQL++ is that it substitutes the current MySQL++ version
    number into several source files.  This allows us to change the
    version number in just one place -- configure.ac -- and have
    it applied to all these other places.  Until you do this step,
    an svn checkout of MySQL++ won't build, because these files with
    the version numbers in them won't be generated.

    Option 1: Copy the generated files over from a released version
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
        Only one of these generated files is absolutely critical to
        allowing MySQL++ to build: lib/mysql++.h.  So, the simplest
        option you have to bootstrap MySQL++ entirely on Windows is to
        copy lib/mysql++.h over from a released version of MySQL++.
        While you're doing that, you might copy over the other such
        generated files:

            install.hta
            mysql++.spec
            doc/userman/userman.dbx
            lib/Doxyfile

        Having done that, you can complete the bootstrapping process by
        running bootstrap.bat.  It has the same purpose as the Bourne
        shell script described above, but much simpler.  It has none
        of the command line options described above, for one thing.

        The main downside of doing it this way is that your changed
        version will have the same version number as the release of
        MySQL++ you copied the files from, unless you go into each
        file and change the version numbers.

    Option 2: Cygwin
    ~~~~~~~~~~~~~~~~
        If you'd like to hack on MySQL++ entirely on Windows and
        have all the build freedoms enjoyed by those working on Unixy
        platforms, the simplest solution is probably to install Cygwin.

        Get the Cygwin installer from http://cygwin.com/setup.exe

        When you run it, it will walk you through the steps to
        install Cygwin.  Autoconf and Perl 5 aren't installed in
        Cygwin by default, so when you get to the packages list,
        be sure to select them.  Autoconf is in the Devel category,
        and Perl 5 in the Interpreters category.

        You will also need to install the native Windows binary
        version of Bakefile, from http://bakefile.org/  Don't get
        the source version and try to build Bakefile under Cygwin; it
        won't work.  The Windows binary version of Bakefile includes
        an embedded version of Python, so you won't need to install
        Cygwin's Python.
        
        Having done all this, you can follow the Unix bootstrapping
        instructions in the previous section.


    Option 3: "Here's a nickel, kid, get yourself a better computer."
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
        http://tomayko.com/writings/that-dilbert-cartoon

        Finally, you might have access to a Unixy system, or the
        ability to set one up.  You don't even need a separate physical
        computer, now that virtual machine techology is free.

        For example, you could download a Linux "appliance" from
        http://www.vmware.com/appliances/ and a copy of the free
        VMware Player to run it on your Windows machine.  You'd do the
        svn checkout of MySQL++ on that machine, bootstrap it there
        using the instructions in the previous section.
        
        That done, just copy the result over to the Windows machine
        to continue hacking on it.


On Manipulating the Build System Source Files
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    One of the things the bootstrapping system described above
    does is produces various types of project and make files from a
    small number of source files.  This system lets us support many
    platforms without having to maintain separate build system files
    for each platform.

    Bakefile (http://bakefile.org/) produces most of these project
    and make files from a single source file called mysql++.bkl.

    Except for small local changes, it's best to change mysql++.bkl
    and "re-bake" the project and make files rather than change
    those files directly.  You can do this with the bootstrap scripts
    covered above.  On Windows, if all you've changed is mysql++.bkl,
    you can use rebake.bat instead, which doesn't try to do as much
    as bootstrap.bat.

    Bakefile produces finished project files for Visual C++ and Xcode
    and finished Makefiles for MinGW.  It also produces Makefile.in,
    which is input to GNU Autoconf along with configure.ac
    and config/*.  You may need to change these latter files in
    addition to or instead of mysql++.bkl to get the effect you want.
    Running bootstrap incorporates changes to all of these files in
    the GNU autoconf output.

    While Bakefile's documentation isn't as comprehensive as it
    ought to be, you can at least count on it to list all of the
    available features.  So, if you can't see a way to make Bakefile
    do something, it's likely it just can't do it.  Bakefile is a
    high-level abstraction of build systems in general, so it'll never
    support all the particulars of every odd build system out there.


Submitting Patches
~~~~~~~~~~~~~~~~~~
    If you wish to submit a patch to the library, please send it to
    the MySQL++ mailing list, or attach it to an entry in our bug
    tracker on Gna!  We want patches in unified diff format.

    The easiest way to get a unified diff is to check out a copy of the
    current MySQL++ tree as described above.  Then make your change,
    cd to the MySQL++ root directory, and ask Subversion to generate
    the diff for you:

        $ svn diff > mychange.patch

    If your patch adds new files to the distribution, you can say
    "svn add newfile" before you do the diff, which will include
    the contents of that file in the patch.  (You can do this even
    when you've checked out the tree anonymously.)  Then say "svn
    revert newfile" to make Subversion forget about the new file.

    If you're making a patch against a MySQL++ distribution tarball,
    then you can generate the diff this way:

        $ diff -ruN mysql++-olddir mysql++-newdir > mychange.patch

    The diff command is part of every Unix and Linux system, and
    should be installed by default.  If you're on a Windows machine,
    GNU diff is part of Cygwin (http://cygwin.com/).  Subversion is
    also available for all of these systems.  There are no excuses
    for not being able to make unified diffs.  :)


The MySQL++ Code Style
~~~~~~~~~~~~~~~~~~~~~~
    Every code base should have a common code style.  Love it or
    hate it, here are MySQL++'s current code style rules:

    Source Code
    ~~~~~~~~~~~
        File types: ac, cpp, h, in, m4, pl

        - Tabs for indents, size 4

        - Unix line endings.  Any decent programmer's editor can
          cope with this, even on Windows.

        - C/C++ rules:

            - Base whitespace style is AT&Tish: K&R/Stroustrup,
              plus a little local spice.  If you have the indent(1)
              program, the command is:

                indent -kr -nce -cli4 -ss -di1 -psl -ts4 FILES...

              That is, don't cuddle else, indent case statement labels,
              space before semicolon with empty loop body, no extra
              space between a variable type and name, return value
              of function on separate line from rest of definition.

            - Class names are in CamelCase, uppercased first letter

            - Method names are in all_lower_case_with_underscores();
              ditto most other global symbols.

            - Macro names are in ALL_UPPERCASE_WITH_UNDERSCORES

            - Doxygen comment for all public declarations, unless
              there is a very good reason to keep the thing
              undocumented.

        - Perl and shell script rules are more or less the same
          as for C/C++, to the extent this makes sense.


    XML/HTML Dialects
    ~~~~~~~~~~~~~~~~~
        File types: bkl, dbx, hta

        - Spaces for indents, size 2.  Shallow indents due to the
          high level of nesting occurring in such files, and spaces
          because they're not as annoying at shallow indent levels
          in editors that don't treat space indents like tabs.

        - Unix line endings.  Again, these are intended to be viewed
          in a programmer's text editor, which should work with Unix
          line endings no matter the platform.


    Plain Text Files
    ~~~~~~~~~~~~~~~~
        File types: txt

        - Spaces for indents, size 4.  Spaces because such files
          are often viewed in Notepad and similarly crippled text
          editors which use a default indent level of 8.

        - DOS line endings, again for the Notepad reason.  And on
          modern Unixy platforms, the tools cope with DOS line endings
          reasonably well.  Better than the converse, anyway.


    When in doubt, mimic what you see in the current code.  When still
    in doubt, ask on the mailing list.


Testing Your Proposed Change
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    MySQL++ includes a self-test mechanism called dtest.  It's a
    Bourne shell script, run much like exrun:

        $ ./dtest [-s server_addr] [-u user] [-p password]

    This automatically runs most of the examples, captures the outputs
    to a file, and then compares that to a known-good run's outputs,
    stored in bmark.txt.  So, before you submit a patch, run dtest
    to see if anything has changed.  If something has and you can't
    account for it, it represents a problem that you'll have to fix
    before submitting the patch.  If it gives an expected change,
    remove bmark.txt, re-run dtest, and include the bmark.txt diffs in
    your patch.  This communicates to us the fact that you know there
    are differences and want the patch evaluated anyway.  Otherwise,
    we are likely to view the change as a bug.

    dtest also runs all of the unit tests in test/*.  The purpose of

    test/* is different from that of examples/*:

        - test/* are unit tests: each tests only one MySQL++ class,
          independent of everything else.  Because DB access requires
          several MySQL++ classes to cooperate, a unit test never
          accesses a database; hence, no unit test needs DB connection
          parameters.  We will never get 100% code coverage from
          test/* alone.


        - examples/* can be thought of as integration tests: they
          test many pieces of MySQL++ working together, accessing

          a real database server.  In addition to ensuring that all
          the pieces work together and give consistent results from
          platform to platform and run to run, it also fills in gaps
          in the code coverage where no suitable test/* module could
          be created.

        - test/* programs always run silently on success, writing
          output only to indicate test failures.  This is because
          they're usually only run via dtest.

        - examples/* are always "noisy," regardless of whether they
          succeed or fail, because they're also run interactively by
          people learning to use MySQL++.





    Patches should include tests if they introduce new functionality
    or fix a bug that the existing test coverage failed to catch.
    If the test is noisy, needs DB access, or tests multiple parts
    of the library at once, it goes in examples/*.  If your change
    affects only one class in MySQL++ and testing it can be done
    without instantiating other MySQL++ classes -- other than by
    composition, of course -- it should go in test/*.


    In general, prefer modifying an existing examples/* or test/*
    program.  Add a new one only if you're introducing brand new
    functionality or when a given feature currently has no test at all.

    Beware that the primary role the examples is to illustrate points
    in the user manual.  If an existing example does something similar
    to what a proper test would need to do and the test doesn't change
    the nature of the example, don't worry about changing the example
    code.  If your test would change the nature of the example, you
    either need to do the test another way, or also submit a change
    to doc/userman/*.dbx that incorporates the difference.


Adding Support for a Different Compiler
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    As described above, MySQL++ uses the Bakefile system for creating
    project files and makefiles.  This allows us to make changes
    to a single set of files, and have the proper changes be made
    to all generated project files and makefiles.  In the past, we
    used more ad-hoc systems, and we'd frequently forget to update
    individual project files and makefiles, so at any given time,
    at least one target was likely to be broken.

    If MySQL++ doesn't currently ship with project files or makefiles
    tuned for your compiler of choice, you need to work through the
    Bakefile mechanism to add support.  We're not willing to do ad-hoc
    platform support any more, so please don't ask if you can send
    us project files instead; we don't want them.

    If you want to port MySQL++ to another platform, we need to be
    confident that the entire library works on your platform before
    we'll accept patches.  In the past, we've had broken ports that
    were missing important library features, or that crashed when built
    in certain ways.  Few people will knowingly use a crippled version
    of MySQL++, since there are usually acceptable alternatives.
    Therefore, such ports become maintenance baggage with little
    compensating value.


Maintaining a Private CVS Repository
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    You may find it helpful to maintain your own CVS repository.
    Whenever there is a new MySQL++ release, import it on the vendor
    branch like this:

        $ cvs import -m "Version 1.7.35" software/mysql++ mysql++ mysql++-1_7_35

    (This assumes that you have your CVSROOT environment variable
    set properly.)

    Update the HEAD branch like this:

        $ cd mysql++
        $ cvs update -PdA
        $ cvs update -j HEAD -j mysql++-1_7_35 -Pd
        $ cvs ci -m "merged 1.7.35 into HEAD"
        $ cvs tag mysql++-1_7_35-merged

    Then any changes you make can easily be tracked, and diffs can
    be produced with rdiff:

        $ cvs rdiff -ru mysql++-1_7_35 -r mysql++-1_7_35_equal_list \
            $(cat CVS/Repository) > equal_list.patch

Changes to examples/ssqls6.cpp.

1

2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

20
21
22
23
24
25
26
27
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
56
57
58
59
60
61
62
63
64
65

66
67
68
69
70
71
72
73
74
75
76
77
78




79
80
81
82

83
84
85

86
87
88
89
90




91
92
93
94
95
96
97

98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115





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
144

/***********************************************************************

 ssqls6.cpp - Example showing how to insert a collection row using the 
 Specialized SQL Structures feature of MySQL++ and Query::insertfrom().

 Copyright (c) 1998 by Kevin Atkinson, (c) 1999-2001 by MySQL AB,
 (c) 2004-2009 by Educational Technology Resources, Inc., (c) 2008 by 
 AboveNet, Inc.  Others may also hold copyrights on code in this file.  
 See the CREDITS file in the top directory of the distribution for details.

 This file is part of MySQL++.

 MySQL++ is free software; you can redistribute it and/or modify it
 under the terms of the GNU Lesser General Public License as published
 by the Free Software Foundation; either version 2.1 of the License, or
 (at your option) any later version.

 MySQL++ is distributed in the hope that it will be useful, but WITHOUT
 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public

 License for more details.

 You should have received a copy of the GNU Lesser General Public
 License along with MySQL++; if not, write to the Free Software
 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
 USA
***********************************************************************/

#include "cmdline.h"
#include "printdata.h"
#include "stock.h"

#include <fstream>



using namespace std;




// Breaks a given text line of tab-separated fields up into a list of
// strings.
static size_t
tokenize_line(const string& line, vector<mysqlpp::String>& strings)
{




	string field;
	strings.clear();

	istringstream iss(line);
	while (getline(iss, field, '\t')) {
		strings.push_back(mysqlpp::String(field));
	}



	return strings.size();
}



// Reads a tab-delimited text file, returning the data found therein
// as a vector of stock SSQLS objects.
static bool
read_stock_items(const char* filename, vector<stock>& stock_vector)
{
	ifstream input(filename);
	if (!input) {
		cerr << "Error opening input file '" << filename << "'" << endl;
		return false;
	}

	string line;

	vector<mysqlpp::String> strings;
	while (getline(input, line)) {
		if (tokenize_line(line, strings) == 6) {
			stock_vector.push_back(stock(string(strings[0]), strings[1],
					strings[2], strings[3], strings[4], strings[5]));
		}
		else {
			cerr << "Error parsing input line (doesn't have 6 fields) " << 
					"in file '" << filename << "'" << endl;
			cerr << "invalid line: '" << line << "'" << endl;
		}
	}





	return true;
}



int
main(int argc, char *argv[])
{

	// Get database access parameters from command line
	mysqlpp::examples::CommandLine cmdline(argc, argv);
	if (!cmdline) {
		return 1;
	}





	// Read in a tab-delimited file of stock data
	vector<stock> stock_vector;
	if (!read_stock_items("examples/stock.txt", stock_vector)) {
		return 1;
	}


	try {
		// Establish the connection to the database server.
		mysqlpp::Connection con(mysqlpp::examples::db_name,
				cmdline.server(), cmdline.user(), cmdline.pass());

		// Clear all existing rows from stock table, as we're about to
		// insert a bunch of new ones, and we want a clean slate.
		mysqlpp::Query query = con.query();
		query.exec("DELETE FROM stock");

		// Insert data read from the CSV file, allowing up to 1000
		// characters per packet.  We're using a small size in this
		// example just to force multiple inserts.  In a real program,
		// you'd want to use larger packets, for greater efficiency.
		mysqlpp::Query::MaxPacketInsertPolicy<> insert_policy(1000);
		query.insertfrom(stock_vector.begin(), stock_vector.end(),
				insert_policy);






		// Retrieve and print out the new table contents.

		print_stock_table(query);
	}
	catch (const mysqlpp::BadQuery& er) {
		// Handle any query errors
		cerr << "Query error: " << er.what() << endl;
		return -1;
	}
	catch (const mysqlpp::BadConversion& er) {
		// Handle bad conversions
		cerr << "Conversion error: " << er.what() << endl <<
				"\tretrieved data size: " << er.retrieved <<
				", actual size: " << er.actual_size << endl;
		return -1;

	}


	catch (const mysqlpp::BadInsertPolicy& er) {

		// Handle bad conversions
		cerr << "InsertPolicy error: " << er.what() << endl;
		return -1;
	}
	catch (const mysqlpp::Exception& er) {

		// Catch-all for any other MySQL++ exceptions
		cerr << "Error: " << er.what() << endl;
		return -1;
	}






	return 0;
}


<
>
|
|

|
|
<
<

|
|
<
<
<
<
|
<
<
<
>
|

<
|
<
<
<
|
|
<
<

<
|
>
>
|


>
>
<
<
<
<
|
>
>
>
>
|
|
|
|
<
<
|
|
>
>
|
<
|
|
>
|
|
|
|
|
|
|
|
|
<
|
|
>
|
|
<
<
<
<
<
<
<
<
|
<
|
>
>
>
>
|
<
|
|
>
|
|
<
>
|
|
|
|
<
>
>
>
>

|
|
|
|
<
|
>
|
|
|
|
|
<
|
<
<
|
<
<
<
<
<
<
<

>
>
>
>
>
|
>
|
|
<
<
<
<
|
<
|
<
<
<
<
>
|
>
>
|
>
|
<
|
|
<
>
|
<
<
<
|
>
>
>
>
>
|
<
|
>

1
2
3
4
5
6


7
8
9




10



11
12
13

14



15
16


17

18
19
20
21
22
23
24
25




26
27
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
56








57

58
59
60
61
62
63

64
65
66
67
68

69
70
71
72
73

74
75
76
77
78
79
80
81
82

83
84
85
86
87
88
89

90


91







92
93
94
95
96
97
98
99
100
101




102

103




104
105
106
107
108
109
110

111
112

113
114



115
116
117
118
119
120
121

122
123

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE sect1 PUBLIC "-//OASIS//DTD DocBook V4.2//EN"
    "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">

<sect1 id="intro">
  <title>Introduction</title>



  <para>MySQL++ is a powerful C++ wrapper for MySQL&#x2019;s
  C API<footnote><para>The MySQL C API is also known as <ulink




  url="https://dev.mysql.com/downloads/connector/c/">Connector/C</ulink>.</para></footnote>.



  Its purpose is to make working with queries as easy as working with
  STL containers.</para>


  <para>The latest version of MySQL++ can be found at <ulink



  url="http://tangentsoft.net/mysql++/">the official web
  site</ulink>.</para>




  <para>Support for MySQL++ can be had on <ulink
  url="http://lists.mysql.com/plusplus">the mailing list</ulink>. That
  page hosts the mailing list archives, and tells you how you can
  subscribe.</para>


  <sect2 id="history">
    <title>A Brief History of MySQL++</title>





    <para>MySQL++ was created in 1998 by Kevin Atkinson. It started
    out MySQL-specific, but there were early efforts to try and
    make it database-independent, and call it SQL++. This is where
    the old library name &#x201C;sqlplus&#x201D; came from. This
    is also why the old versions prefixed some class names with
    &#x201C;Mysql&#x201D; but not others: the others were supposed to
    be the database-independent parts. All of Kevin&#x2019;s releases
    had pre-1.0 version numbers.</para>



    <para>Then in 1999, <ulink url="http://www.mysql.com/">MySQL
    AB</ulink> took over development of the library. In the beginning,
    <ulink url="http://en.wikipedia.org/wiki/Monty_Widenius">Monty
    Widenius</ulink> himself did some of the work, but later gave it

    over to another MySQL employee, Sinisa Milivojevic. MySQL released
    versions 1.0 and 1.1, and then Kevin gave over maintenance to
    Sinisa officially with 1.2, and ceased to have any involvement
    with the library&#x2019;s maintenance. Sinisa went on to maintain
    the library through 1.7.9, released in mid-2001. It seems to be
    during this time that the dream of multiple-database compatibility
    died, for obvious reasons.</para>

    <para>With version 1.7.9, MySQL++ went into a period of
    stasis, lasting over three years. (Perhaps it was the
    ennui and retrenchment following the collapse of <ulink
    url="http://en.wikipedia.org/wiki/Dot-com_bubble">the

    bubble</ulink> that caused them to lose interest.) During this
    time, Sinisa ran the MySQL++ mailing list and supported its users,
    but made no new releases. Contributed patches were either ignored
    or put up on the MySQL++ web site for users to try, without any
    official blessing.</para>










    <para>The biggest barrier to using MySQL++ during this period
    is that the popular C++ compilers of 2001 weren&#x2019;t all
    that compatible with the C++ Standard. As a result, MySQL++
    used many nonstandard constructs, to allow for compatibility
    with older compilers. Each new compiler released in the
    following years increased compliance, either warning

    about or rejecting code using pre-Standard constructs.
    In particular, <ulink url="http://gcc.gnu.org/">GCC</ulink>
    was emerging from the mess following the <ulink
    url="http://en.wikipedia.org/wiki/GNU_Compiler_Collection#EGCS">EGCS
    fork</ulink> during this time. The fork was healed officially

    in 1999, but there&#x2019;s always a delay of a few years between
    the release of a new GCC and widespread adoption. The post-EGCS
    versions of GCC were only beginning to become popular by 2001,
    when development on MySQL++ halted. As a result, it became
    increasingly difficult to get MySQL++ to build cleanly as newer

    compilers came out. Since MySQL++ uses templates heavily, this
    affected end user programs as well: MySQL++ code got included
    directly in your program, so any warnings or errors it caused
    became your program&#x2019;s problem.</para>

    <para>As a result, most of the patches contributed to the MySQL++
    project during this period were to fix up standards compliance
    issues. Because no one was bothering to officially test and bless
    these patches, you ended up with the worst aspects of a <ulink

    url="http://en.wikipedia.org/wiki/The_Cathedral_and_the_Bazaar">bazaar</ulink>
    development model: complete freedom of development, but no guiding
    hand to select from the good stuff and reject the rest. Many of the
    patches were mutually incompatible. Some would build upon other
    patches, so you had to apply them in the proper sequence. Others
    did useful things, but didn&#x2019;t give a fully functional copy of
    MySQL++. Figuring out which patch(es) to use was an increasingly

    frustrating exercise as the years wore on, and newer GCCs became


    popular.</para>








    <para>In early August of 2004, Warren Young got fed up with this
    situation and took over. He released 1.7.10 later that month,
    which did little more than make the code build with GCC 3.3 without
    warnings. Since then, with a little help from his friends on the
    Net, MySQL++ has lost a lot of bugs, gained a lot of features,
    gained a few more bugs, lost them again... MySQL++ is alive and
    healthy now.</para>
  </sect2>







  <sect2 id="asking-questions">




    <title>If You Have Questions...</title>

    <para>If you want to email someone to ask questions about
    this library, we greatly prefer that you send mail to the
    <ulink url="http://lists.mysql.com/plusplus">MySQL++ mailing
    list</ulink>. The mailing list is archived, so if you have
    questions, do a search to see if the question has been asked

    before.</para>


    <para>You may find people&#x2019;s individual email addresses in various
    files within the MySQL++ distribution. Please do not send mail



    to them unless you are sending something that is inherently
    personal. Not all of the principal developers of MySQL++ are still
    active in its development; those who have dropped out have no wish
    to be bugged about MySQL++. Those of us still active in MySQL++
    development monitor the mailing list, so you aren&#x2019;t getting any
    extra &#x201C;coverage&#x201D; by sending messages to additional
    email addresses.</para>

  </sect2>
</sect1>

Changes to examples/stock.h.




1


2






3












4







5


6


7




8






9


10




11




12



13







14






15







16



17









18
19


20





21






22












23



















24



25

















26


27


28













































































































29
30
31
32
33
34
35


36
37
38
39
40
41
42
43





44




45
46




47














/***********************************************************************


 stock.h - Declares the stock SSQLS used by several of the examples.



















 Copyright (c) 1998 by Kevin Atkinson, (c) 1999-2001 by MySQL AB, and







 (c) 2004-2010 by Educational Technology Resources, Inc.  Others may


 also hold copyrights on code in this file.  See the CREDITS.txt file


 in the top directory of the distribution for details.











 This file is part of MySQL++.







 MySQL++ is free software; you can redistribute it and/or modify it




 under the terms of the GNU Lesser General Public License as published



 by the Free Software Foundation; either version 2.1 of the License, or







 (at your option) any later version.














 MySQL++ is distributed in the hope that it will be useful, but WITHOUT



 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or









 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
 License for more details.








 You should have received a copy of the GNU Lesser General Public






 License along with MySQL++; if not, write to the Free Software












 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301



















 USA



***********************************************************************/




















#include <mysql++.h>


#include <ssqls.h>














































































































// The following is calling a very complex macro which will create
// "struct stock", which has the member variables:
//
//   sql_char item;
//   ...
//   sql_mediumtext_null description;


//
// plus methods to help populate the class from a MySQL row.  See the
// SSQLS sections in the user manual for further details.
sql_create_6(stock,
	1, 6, // The meaning of these values is covered in the user manual
	mysqlpp::sql_char, item,
	mysqlpp::sql_bigint, num,
	mysqlpp::sql_double, weight,





	mysqlpp::sql_double_null, price,




	mysqlpp::sql_date, sDate,			// SSQLS isn't case-sensitive!
	mysqlpp::sql_mediumtext_null, description)
















>
>
>
|
>
>
|
>
>
>
>
>
>

>
>
>
>
>
>
>
>
>
>
>
>
|
>
>
>
>
>
>
>
|
>
>
|
>
>
|
>
>
>
>

>
>
>
>
>
>
|
>
>

>
>
>
>
|
>
>
>
>
|
>
>
>
|
>
>
>
>
>
>
>
|
>
>
>
>
>
>

>
>
>
>
>
>
>
|
>
>
>
|
>
>
>
>
>
>
>
>
>
|
|
>
>

>
>
>
>
>
|
>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

>
>
|
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

|
|
|
|
|
|
>
>
|
|
<
<
|
|
|
|
>
>
>
>
>
|
>
>
>
>
|
<
>
>
>
>

>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
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
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
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
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
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
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
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
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
336
<?xml version="1.0" encoding='UTF-8'?>
<!DOCTYPE sect1 PUBLIC "-//OASIS//DTD DocBook V4.2//EN"
    "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">

<sect1 id="threads">
  <title>Using MySQL++ in a Multithreaded Program</title>

  <para>MySQL++ is not &#x201C;thread safe&#x201D; in any
  meaningful sense. MySQL++ contains very little code that
  actively prevents trouble with threads, and all of it is
  optional. We have done some work in MySQL++ to make thread
  safety <emphasis>achievable</emphasis>, but it doesn&#x2019;t come
  for free.</para>

  <para>The main reason for this is that MySQL++ is
  generally I/O-bound, not processor-bound. That is, if
  your program&#x2019;s bottleneck is MySQL++, the ultimate
  cause is usually the I/O overhead of using a client-server
  database. Doubling the number of threads will just let your
  program get back to waiting for I/O twice as fast. Since <ulink
  url="http://www.eecs.berkeley.edu/Pubs/TechRpts/2006/EECS-2006-1.pdf">threads
  are evil</ulink> and generally can&#x2019;t help MySQL++, the only
  optional thread awareness features we turn on in the shipping
  version of MySQL++ are those few that have no practical negative
  consequences. Everything else is up to you, the programmer, to
  evaluate and enable as and when you need it.</para>

  <para>We&#x2019;re going to assume that you are reading this chapter
  because you find yourself needing to use threads for some other
  reason than to speed up MySQL access. Our purpose here is limited
  to setting down the rules for avoiding problems with MySQL++ in a
  multi-threaded program. We won&#x2019;t go into the broader issues of
  thread safety outside the scope of MySQL++. You will need a grounding
  in threads in general to get the full value of this advice.</para>

  <sect2 id="thread-build">
    <title>Build Issues</title>

    <para>Before you can safely use MySQL++ with threads, there are
    several things you must do to get a thread-aware build:</para>

    <orderedlist>
      <listitem>
        <para><emphasis>Build MySQL++ itself with thread awareness
        turned on.</emphasis></para>

        <para>On Linux, Cygwin and Unix (OS X, *BSD, Solaris...),
        pass the <computeroutput>--enable-thread-check</computeroutput>
        flag to the <filename>configure</filename> script. Beware, this
        is only a request to the <filename>configure</filename> script
        to look for thread support on your system, not a requirement
        to do or die: if the script doesn&#x2019;t find what it needs
        to do threading, MySQL++ will just get built without thread
        support. See <filename>README-Unix.txt</filename> for more
        details.</para>

        <para>On Windows, if you use the Visual C++ project files or
        the MinGW Makefile that comes with the MySQL++ distribution,
        threading is always turned on, due to the nature of
        Windows.</para>

        <para>If you build MySQL++ in some other way, such as with
        Dev-Cpp (based on MinGW) you&#x2019;re on your own to enable
        thread awareness.</para>
      </listitem>

      <listitem>
        <para><emphasis>Link your program to a thread-aware build of the
        MySQL C API library.</emphasis></para>

        <para>If you use a binary distribution of MySQL on Unixy
        systems, you usually get two different versions of the MySQL
        C API library, one with thread support and one without. These
        are typically called <filename>libmysqlclient</filename> and
        <filename>libmysqlclient_r</filename>, the latter being the
        thread-safe one. (The &#x201C;<filename>_r</filename>&#x201D;
        means reentrant.)</para>

        <para>If you&#x2019;re using the Windows binary distribution
        of MySQL, you should have only one version of the C
        API library, which should be thread-aware. If you have
        two, you probably just have separate debug and optimized
        builds. See <filename>README-Visual-C++.txt</filename> or
        <filename>README-MinGW.txt</filename> for details.</para>

        <para>If you build MySQL from source, you might only get
        one version of the MySQL C API library, and it can have
        thread awareness or not, depending on your configuration
        choices. This is the case with Cygwin, where you currently
        have no choice but to build the C API library from source. (See
        <filename>README-Cygwin.txt</filename>.)</para>
      </listitem>

      <listitem>
        <para><emphasis>Enable threading in your program&#x2019;s build
        options.</emphasis></para>

        <para>This is different for every platform, but it&#x2019;s
        usually the case that you don&#x2019;t get thread-aware builds
        by default. Depending on the platform, you might need to change
        compiler options, linker options, or both. See your development
        environment&#x2019;s documentation, or study how MySQL++ itself
        turns on thread-aware build options when requested.</para>
      </listitem>
    </orderedlist>
  </sect2>


  <sect2 id="thread-conn-mgmt">
    <title>Connection Management</title>

    <para>The MySQL C API underpinning MySQL++ does not allow multiple
    concurrent queries on a single connection. You can run into this
    problem in a single-threaded program, too, which is why we cover the
    details elsewhere, in <xref linkend="concurrentqueries"/>.
    It&#x2019;s a thornier problem when using threads, though.</para>

    <para>The simple fix is to just create a separarate <ulink
    url="Connection" type="classref"/> object for each thread that
    needs to make database queries. This works well if you have a small
    number of threads that need to make queries, and each thread uses
    its connection often enough that the server doesn&#x2019;t <link
    linkend="conn-timeout">time out</link> waiting for queries.</para>

    <para>If you have lots of threads or the frequency of queries is
    low, the connection management overhead will be excessive. To avoid
    that, we created the <ulink url="ConnectionPool" type="classref"/>
    class. It manages a pool of <classname>Connection</classname>
    objects like library books: a thread checks one out, uses
    it, and then returns it to the pool as soon as it&#x2019;s
    done with it. This keeps the number of active connections
    low. We suggest that you keep each connection&#x2019;s
    use limited to a single variable scope for <ulink
    url="http://en.wikipedia.org/wiki/RAII">RAII</ulink> reasons;
    we created a little helper called <ulink url="ScopedConnection"
    type="classref"/> to make that easy.</para>

    <para><classname>ConnectionPool</classname> has three
    methods that you need to override in a subclass to
    make it concrete: <methodname>create()</methodname>,
    <methodname>destroy()</methodname>, and
    <methodname>max_idle_time()</methodname>. These overrides let
    the base class delegate operations it can&#x2019;t successfully do
    itself to its subclass. The <classname>ConnectionPool</classname>
    can&#x2019;t know how to <methodname>create()</methodname>
    the <classname>Connection</classname> objects, because that
    depends on how your program gets login parameters, server
    information, etc.  <classname>ConnectionPool</classname>
    also makes the subclass <methodname>destroy()</methodname>
    the <classname>Connection</classname> objects it created; it
    could assume that they&#x2019;re simply allocated on the heap
    with <methodname>new</methodname>, but it can&#x2019;t be sure,
    so the base class delegates destruction, too. Finally, the base
    class can&#x2019;t know what the connection idle timeout policy
    in the client would make the most sense, so it asks its subclass
    via the <methodname>max_idle_time()</methodname> method.</para>

    <para><classname>ConnectionPool</classname> also allows you to
    override <methodname>release()</methodname>, if needed. For simple
    uses, it&#x2019;s not necessary to override this.</para>

    <para>In designing your <classname>ConnectionPool</classname>
    derivative, you might consider making it a <ulink
    url="http://en.wikipedia.org/wiki/Singleton_pattern">Singleton</ulink>,
    since there should only be one pool in a program.</para>

    <para>Another thing you might consider doing is passing a
    <ulink url="ReconnectOption" type="classref"/> object to
    <methodname>Connection::set_option()</methodname> in your
    <methodname>create()</methodname> override before returning the
    new <classname>Connection</classname> pointer. This will cause
    the underlying MySQL C API to try to reconnect to the database
    server if a query fails because the connection was dropped
    by the server. This can happen if the DB server is allowed to
    restart out from under your application. In many applications,
    this isn&#x2019;t allowed, or if it does happen, you might want
    your code to be able to detect it, so MySQL++ doesn&#x2019;t set
    this option for you automatically.</para>

    <para>Here is an example showing how to use connection pools with
    threads:</para>

    <programlisting><xi:include href="cpool.txt" parse="text"
    xmlns:xi="http://www.w3.org/2001/XInclude"/></programlisting>

    <para>The example works with both Windows native
    threads and with POSIX threads.<footnote><para>The file
    <filename>examples/threads.h</filename> contains a few macros and
    such to abstract away the differences between the two threading
    models.</para></footnote> Because thread-enabled builds are only
    the default on Windows, it&#x2019;s quite possible for this program
    to do nothing on other platforms. See above for instructions on
    enabling a thread-aware build.</para>

    <para>If you write your code without checks for thread support
    like you see in the code above and link it to a build of MySQL++
    that isn&#x2019;t thread-aware, it will still try to run. The
    threading mechanisms fall back to a single-threaded mode when
    threads aren&#x2019;t available. A particular danger is that the
    mutex lock mechanism used to keep the pool&#x2019;s internal data
    consistent while multiple threads access it will just quietly
    become a no-op if MySQL++ is built without thread support. We do
    it this way because we don&#x2019;t want to make thread support
    a MySQL++ prerequisite. And, although it would be of limited
    value, this lets you use <classname>ConnectionPool</classname>
    in single-threaded programs.</para>

    <para>You might wonder why we don&#x2019;t just work around
    this weakness in the C API transparently in MySQL++ instead of
    suggesting design guidelines to avoid it. We&#x2019;d like to do
    just that, but how?</para>

    <para>If you consider just the threaded case, you could argue for
    the use of mutexes to protect a connection from trying to execute
    two queries at once. The cure is worse than the disease: it turns a
    design error into a performance sap, as the second thread is blocked
    indefinitely waiting for the connection to free up. Much better to
    let the program get the &#x201C;Commands out of sync&#x201D; error,
    which will guide you to this section of the manual, which tells you
    how to avoid the error with a better design.</para>

    <para>Another option would be to bury
    <classname>ConnectionPool</classname> functionality within MySQL++
    itself, so the library could create new connections at need.
    That&#x2019;s no good because the above example is the most complex
    in MySQL++, so if it were mandatory to use connection pools, the
    whole library would be that much more complex to use. The whole
    point of MySQL++ is to make using the database easier. MySQL++
    offers the connection pool mechanism for those that really need it,
    but an option it must remain.</para>
  </sect2>


  <sect2 id="thread-helpers">
    <title>Helper Functions</title>

    <para><classname>Connection</classname> has several thread-related
    static methods you might care about when using MySQL++ with
    threads.</para>

    <para>You can call
    <methodname>Connection::thread_aware()</methodname> to
    determine whether MySQL++ and the underlying C API library were
    both built to be thread-aware. I want to stress that thread
    <emphasis>awareness</emphasis> is not the same thing as thread
    <emphasis>safety</emphasis>: it&#x2019;s still up to you to make
    your code thread-safe. If this method returns true, it just means
    it&#x2019;s <emphasis>possible</emphasis> to achieve thread-safety,
    not that you actually have it.</para>

    <para>If your program&#x2019;s connection-management strategy
    allows a thread to use a <classname>Connection</classname>
    object that another thread created, you need to know
    about <methodname>Connection::thread_start()</methodname>.
    This function sets up per-thread resources needed to make MySQL
    server calls. You don&#x2019;t need to call it when you use the
    simple <classname>Connection</classname>-per-thread strategy,
    because this function is implicitly called the first time you
    create a <classname>Connection</classname> in a thread. It&#x2019;s
    not harmful to call this function from a thread that previously
    created a <classname>Connection</classname>, just unnecessary. The
    only time it&#x2019;s necessary is when a thread can make calls
    to the database server on a <classname>Connection</classname>
    that another thread created and that thread hasn&#x2019;t already
    created a <classname>Connection</classname> itself.</para>

    <para>If you use <classname>ConnectionPool</classname>, you should
    call <methodname>thread_start()</methodname> at the start of each
    worker thread because you probably can&#x2019;t reliably predict
    whether your <methodname>grab()</methodname> call will create a new
    <classname>Connection</classname> or will return one previously
    returned to the pool from another thread.  It&#x2019;s possible
    to conceive of situations where you can guarantee that each pool
    user always creates a fresh <classname>Connection</classname> the
    first time it calls <methodname>grab()</methodname>, but thread
    programming is complex enough that it&#x2019;s best to take the
    safe path and always call <methodname>thread_start()</methodname>
    early in each worker thread.</para>

    <para>Finally, there&#x2019;s the complementary method,
    <methodname>Connection::thread_end()</methodname>. Strictly
    speaking, it&#x2019;s not <emphasis>necessary</emphasis> to call
    this. The per-thread memory allocated by the C API is small,
    it doesn&#x2019;t grow over time, and a typical thread is going
    to need this memory for its entire run time. Memory debuggers
    aren&#x2019;t smart enough to know all this, though, so they will
    gripe about a memory leak unless you call this from each thread
    that uses MySQL++ before that thread exits.</para>

    <para>Although its name suggests otherwise,
    <methodname>Connection::thread_id()</methodname> has nothing to
    do with anything in this chapter.</para>
  </sect2>


  <sect2 id="thread-data-sharing">
    <title>Sharing MySQL++ Data Structures</title>

    <para>We&#x2019;re in the process of making it safer to share
    MySQL++&#x2019;s data structures across threads. Although things
    are getting better, it&#x2019;s highly doubtful that all problems
    with this are now fixed. By way of illustration, allow me explain
    one aspect of this problem and how we solved it in MySQL++
    3.0.0.</para>



    <para>When you issue a database query that returns rows, you
    also get information about the columns in each row. Since the
    column information is the same for each row in the result set,
    older versions of MySQL++ kept this information in the result
    set object, and each <ulink url="Row" type="classref"/> kept
    a pointer back to the result set object that created it so it
    could access this common data at need. This was fine as long as
    each result set object outlived the <classname>Row</classname>
    objects it returned.  It required uncommon usage patterns to run
    into trouble in this area in a single-threaded program, but in
    a multi-threaded program it was easy. For example, there&#x2019;s
    frequently a desire to let one connection do the queries, and other
    threads process the results.  You can see how avoiding lifetime
    problems here would require a careful locking strategy.</para>


    <para>We got around this in MySQL++ v3.0 by giving these shared data
    structures a lifetime independent of the result set object that
    intitially creates it. These shared data structures stick around
    until the last object needing them gets destroyed.</para>

    <para>Although this is now a solved problem, I bring it up because
    there are likely other similar lifetime and sequencing problems
    waiting to be discovered inside MySQL++. If you would like to
    help us find these, by all means, share data between threads
    willy-nilly.  We welcome your crash reports on the MySQL++
    mailing list. But if you&#x2019;d prefer to avoid problems,
    it&#x2019;s better to keep all data about a query within a single
    thread. Between this and the advice in prior sections, you should
    be able to use threads with MySQL++ without trouble.</para>
  </sect2>
</sect1>

Changes to examples/stock.txt.


1

2




3


































































































































































































































































































































































































4



5
































































































































































































6



7


































































































































































































8








9







10

























































































































































































































































































































































































11


12
































































































































































































13


14



































































































































































































15
16

17






































































































































































































































































































































































































18







19



20































































































































































































































































































































































































21




22


23

































































































































































































































































































































































































24

25

26








































































































































































































































































































































































































Tiny Screws	1000	0.01	0.05	2008-11-11	All those tiny, indistinguishable, but slighly different screws like the ones it the bottom of your computer desk drawer.

Needle-nose Pliers	50	0.5	5.95	2008-11-12	Drop-forged steel, rubberized grip




Small Soldering Iron	40	0.5	15.95	2008-09-01	20-watt model, assorted tips, UL approved


































































































































































































































































































































































































Large Soldering Iron	35	0.75	24.95	2008-08-01	40-watt model, assorted tips, UL approved, stand included



Solder Wick	100	0.1	2.95	2008-04-01	25 feet, braided copper
































































































































































































Mini Screwdrivers, 3 pc.	30	0.4	8.95	2008-03-25	3-piece mini-screwdriver set in plastic case, 2 Phillips, 1 standard slot



Mini Screwdrivers, 6 pc.	40	0.6	12.95	2008-04-01	6-piece mini-screwdriver set in plastic case, 3 Phillips, 3 standard slot


































































































































































































Wire-wrapping Tool	25	0.2	4.95	2008-04-23	wire-wrapping tool with rubberied grip








Red LED, 5mm, 3000mcd	300	0.01	0.29	2008-10-02	Max forward current 20mA continuous. Max Forward Drop: 2.1V. Max reverse Voltage:5VDC.







Orange LED, 5mm, 2500mcd	250	0.01	0.29	2008-07-31	Max forward current 20mA continuous, 5VDC Max reverse Voltage. 2VDC (typ) Forward voltage drop. 30 Deg. view angle. 1" leads.

























































































































































































































































































































































































Yellow LED, 5mm, 3000mcd	400	0.01	0.25	2008-09-30	Max forward current 20mA continuous, 5VDC Max reverse Voltage. 2.2VDC (typ) Forward voltage drop. 30 Deg. view angle. 1" leads.


Green LED, 5mm, 1000mcd	350	0.01	0.45	2008-09-27	Max forward current 20mA continuous, 5VDC Max reverse Voltage. 2VDC (typ) Forward voltage drop. 30 Deg. view angle. 1" leads.
































































































































































































Blue LED, 5mm, 3900mcd	500	0.01	0.34	2007-12-01	Max forward current 20mA continuous, 5VDC Max reverse Voltage. 2.2VDC (typ) Forward voltage drop. 30 Deg. view angle. 1" leads.


White LED, 5mm, 15000mcd	750	0.01	0.43	2008-02-01	Max forward current 30mA continuous, 20mA recommended. 5VDC Max reverse Voltage. 3.8VDC typ. 4.5V max. Forward voltage drop. 15deg. View angle. 1" leads.



































































































































































































AA Battery, single	220	0.05	0.50	2007-09-19	1.5 v, alkaline
AA Battery, 4-pack	60	0.20	1.79	2007-08-03	1.5 v, alkaline

AA Battery, 24-pack	8	1.2	9.99	2007-04-25	1.5 v, alkaline, includes tester






































































































































































































































































































































































































C Battery, single	100	0.075	0.65	2007-11-14	1.5 v, alkaline







C Battery, 4-pack	25	0.3	2.29	2007-06-05	1.5 v, alkaline



C Battery, 24-pack	5	1.8	10.99	2007-06-13	1.5 v, alkaline, includes tester































































































































































































































































































































































































D Battery, single	180	0.08	0.70	2007-12-03	1.5 v, alkaline




D Battery, 4-pack	45	0.3	2.59	2007-04-01	1.5 v, alkaline


D Battery, 24-pack	12	1.9	11.99	2007-05-15	1.5 v, alkaline, includes tester

































































































































































































































































































































































































9-volt Battery, single	90	0.06	0.75	2008-01-02	alkaline

9-volt Battery, 3-pack	17	0.2	1.99	2008-02-28	alkaline

9-volt Batter, 20-pack	12	1.2	12.99	2007-12-28	alkaline, no tester needed (just use your tongue)







































































































































































































































































































































































































>
|
>
|
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
|
>
>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
|
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
>
>
>
>
>
>
|
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
>
>
>
|
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
|
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
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
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
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
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
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
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
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
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
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
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
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
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
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
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
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
1694
1695
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
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
1883
1884
1885
1886
1887
1888
1889
1890
1891
1892
1893
1894
1895
1896
1897
1898
1899
1900
1901
1902
1903
1904
1905
1906
1907
1908
1909
1910
1911
1912
1913
1914
1915
1916
1917
1918
1919
1920
1921
1922
1923
1924
1925
1926
1927
1928
1929
1930
1931
1932
1933
1934
1935
1936
1937
1938
1939
1940
1941
1942
1943
1944
1945
1946
1947
1948
1949
1950
1951
1952
1953
1954
1955
1956
1957
1958
1959
1960
1961
1962
1963
1964
1965
1966
1967
1968
1969
1970
1971
1972
1973
1974
1975
1976
1977
1978
1979
1980
1981
1982
1983
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993
1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
2027
2028
2029
2030
2031
2032
2033
2034
2035
2036
2037
2038
2039
2040
2041
2042
2043
2044
2045
2046
2047
2048
2049
2050
2051
2052
2053
2054
2055
2056
2057
2058
2059
2060
2061
2062
2063
2064
2065
2066
2067
2068
2069
2070
2071
2072
2073
2074
2075
2076
2077
2078
2079
2080
2081
2082
2083
2084
2085
2086
2087
2088
2089
2090
2091
2092
2093
2094
2095
2096
2097
2098
2099
2100
2101
2102
2103
2104
2105
2106
2107
2108
2109
2110
2111
2112
2113
2114
2115
2116
2117
2118
2119
2120
2121
2122
2123
2124
2125
2126
2127
2128
2129
2130
2131
2132
2133
2134
2135
2136
2137
2138
2139
2140
2141
2142
2143
2144
2145
2146
2147
2148
2149
2150
2151
2152
2153
2154
2155
2156
2157
2158
2159
2160
2161
2162
2163
2164
2165
2166
2167
2168
2169
2170
2171
2172
2173
2174
2175
2176
2177
2178
2179
2180
2181
2182
2183
2184
2185
2186
2187
2188
2189
2190
2191
2192
2193
2194
2195
2196
2197
2198
2199
2200
2201
2202
2203
2204
2205
2206
2207
2208
2209
2210
2211
2212
2213
2214
2215
2216
2217
2218
2219
2220
2221
2222
2223
2224
2225
2226
2227
2228
2229
2230
2231
2232
2233
2234
2235
2236
2237
2238
2239
2240
2241
2242
2243
2244
2245
2246
2247
2248
2249
2250
2251
2252
2253
2254
2255
2256
2257
2258
2259
2260
2261
2262
2263
2264
2265
2266
2267
2268
2269
2270
2271
2272
2273
2274
2275
2276
2277
2278
2279
2280
2281
2282
2283
2284
2285
2286
2287
2288
2289
2290
2291
2292
2293
2294
2295
2296
2297
2298
2299
2300
2301
2302
2303
2304
2305
2306
2307
2308
2309
2310
2311
2312
2313
2314
2315
2316
2317
2318
2319
2320
2321
2322
2323
2324
2325
2326
2327
2328
2329
2330
2331
2332
2333
2334
2335
2336
2337
2338
2339
2340
2341
2342
2343
2344
2345
2346
2347
2348
2349
2350
2351
2352
2353
2354
2355
2356
2357
2358
2359
2360
2361
2362
2363
2364
2365
2366
2367
2368
2369
2370
2371
2372
2373
2374
2375
2376
2377
2378
2379
2380
2381
2382
2383
2384
2385
2386
2387
2388
2389
2390
2391
2392
2393
2394
2395
2396
2397
2398
2399
2400
2401
2402
2403
2404
2405
2406
2407
2408
2409
2410
2411
2412
2413
2414
2415
2416
2417
2418
2419
2420
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
2475
2476
2477
2478
2479
2480
2481
2482
2483
2484
2485
2486
2487
2488
2489
2490
2491
2492
2493
2494
2495
2496
2497
2498
2499
2500
2501
2502
2503
2504
2505
2506
2507
2508
2509
2510
2511
2512
2513
2514
2515
2516
2517
2518
2519
2520
2521
2522
2523
2524
2525
2526
2527
2528
2529
2530
2531
2532
2533
2534
2535
2536
2537
2538
2539
2540
2541
2542
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
2587
2588
2589
2590
2591
2592
2593
2594
2595
2596
2597
2598
2599
2600
2601
2602
2603
2604
2605
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
2657
2658
2659
2660
2661
2662
2663
2664
2665
2666
2667
2668
2669
2670
2671
2672
2673
2674
2675
2676
2677
2678
2679
2680
2681
2682
2683
2684
2685
2686
2687
2688
2689
2690
2691
2692
2693
2694
2695
2696
2697
2698
2699
2700
2701
2702
2703
2704
2705
2706
2707
2708
2709
2710
2711
2712
2713
2714
2715
2716
2717
2718
2719
2720
2721
2722
2723
2724
2725
2726
2727
2728
2729
2730
2731
2732
2733
2734
2735
2736
2737
2738
2739
2740
2741
2742
2743
2744
2745
2746
2747
2748
2749
2750
2751
2752
2753
2754
2755
2756
2757
2758
2759
2760
2761
2762
2763
2764
2765
2766
2767
2768
2769
2770
2771
2772
2773
2774
2775
2776
2777
2778
2779
2780
2781
2782
2783
2784
2785
2786
2787
2788
2789
2790
2791
2792
2793
2794
2795
2796
2797
2798
2799
2800
2801
2802
2803
2804
2805
2806
2807
2808
2809
2810
2811
2812
2813
2814
2815
2816
2817
2818
2819
2820
2821
2822
2823
2824
2825
2826
2827
2828
2829
2830
2831
2832
2833
2834
2835
2836
2837
2838
2839
2840
2841
2842
2843
2844
2845
2846
2847
2848
2849
2850
2851
2852
2853
2854
2855
2856
2857
2858
2859
2860
2861
2862
2863
2864
2865
2866
2867
2868
2869
2870
2871
2872
2873
2874
2875
2876
2877
2878
2879
2880
2881
2882
2883
2884
2885
2886
2887
2888
2889
2890
2891
2892
2893
2894
2895
2896
2897
2898
2899
2900
2901
2902
2903
2904
2905
2906
2907
2908
2909
2910
2911
2912
2913
2914
2915
2916
2917
2918
2919
2920
2921
2922
2923
2924
2925
2926
2927
2928
2929
2930
2931
2932
2933
2934
2935
2936
2937
2938
2939
2940
2941
2942
2943
2944
2945
2946
2947
2948
2949
2950
2951
2952
2953
2954
2955
2956
2957
2958
2959
2960
2961
2962
2963
2964
2965
2966
2967
2968
2969
2970
2971
2972
2973
2974
2975
2976
2977
2978
2979
2980
2981
2982
2983
2984
2985
2986
2987
2988
2989
2990
2991
2992
2993
2994
2995
2996
2997
2998
2999
3000
3001
3002
3003
3004
3005
3006
3007
3008
3009
3010
3011
3012
3013
3014
3015
3016
3017
3018
3019
3020
3021
3022
3023
3024
3025
3026
3027
3028
3029
3030
3031
3032
3033
3034
3035
3036
3037
3038
3039
3040
3041
3042
3043
3044
3045
3046
3047
3048
3049
3050
3051
3052
3053
3054
3055
3056
3057
3058
3059
3060
3061
3062
3063
3064
3065
3066
3067
3068
3069
3070
3071
3072
3073
3074
3075
3076
3077
3078
3079
3080
3081
3082
3083
3084
3085
3086
3087
3088
3089
3090
3091
3092
3093
3094
3095
3096
3097
3098
3099
3100
3101
3102
3103
3104
3105
3106
3107
3108
3109
3110
3111
3112
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
3146
3147
3148
3149
3150
3151
3152
3153
3154
3155
3156
3157
3158
3159
3160
3161
3.2.3, 2016.12.29 (r2790)

    o Now using snprintf() instead of _snprintf() on Visual C++ 2015.

    o Cygwin changed its naming for the MySQL C API library since the
      last time we successfully tried building MySQL++ there.  Reworked
      the autoconf detection macro to make it less dependent on such
      individual platform differences.

      The macro is in fact now entirely side-effect-free, just setting
      MYSQL_C_* variables that the top-level Bakefile uses when and
      as it needs them, rather than expecting that major variables
      like CPPLFAGS and LIBS were overridden by the autoconf macro.
      This makes the autoconf case more like that of the non-autoconf
      Bakefile outputs.

    o Squished a Clang warning


3.2.2, 2015.03.18 (r2780)

    o The DBDriver::operator= would leak a live connection if you
      assigned a disconnected DBDriver to it.  Patch by Quentin Armitage.

    o Plugged a potential DBDriver instance leak in Connection ctor.
      Patch by Yury Alekseev.

    o Explicitly #including algorithm.h in examples/multiquery.cpp for
      std::max().

    o Added missing "break;" statements in Transaction ctor taking an
      isolation level parameter, which caused only the last one to do
      the right thing.  Problem noticed by Tony Whyman, fix by me.

    o The bootstrap script now checks for the existence of needed build
      tools before trying to use them.  This lets us emit a clearer
      error message than the shell will.  Original patch by Adrian
      Cornish.

    o Fixed a build problem related to std::min/max with Visual C++ 2013
      due to a change in the definitions provided by its header files.

    o Tracked several changes made to Connector/C made since 3.2.1.

    o Assorted documentation updates.

    o Generating HTML with UTF-8 encoding, not 8859-1


3.2.1, 2013.12.10 (r2756)

    o Connection copy ctor wasn't copying the "throw exceptions"
      flag.  The copy always had exceptions enabled.

    o The resetdb example would print a bogus message about logging in
      as '1'@'1' instead of showing the actual values passed on the
      command line.  This did not affect how it actually logged in.

    o Previous release tarball was missing a few text files present in
      the source repository.

    o Updated build paths for VC++ and MinGW to track a file layout
      change in Connector/C 6.1.2.


3.2.0, 2013.06.20 (r2747)

    o References to MySQL 5.1 have been replaced with 5.6, that
      being the current GA release.

    o All Windows builds now assume you're using Connector/C 6.1
      instead of having installed the MySQL server on your machine
      just to get development files.  If you are running a MySQL
      server on your development machine and don't want to install
      Connector/C just to make MySQL++ happy, see the README-*.txt
      file for your platform to get instructions on fixing the paths
      so the build system finds the development files under the MySQL
      server directory.

    o The generated VC++ 2008 project files now assume you want 64-bit
      executables.  (It is 2013 now, after all.)

      Since the VC++ 2005 project files continue to be configured for
      32-bit builds, the easiest way to get a 32-bit project in VC++
      2008+ is to import the VC++ *2005* project files, rather than
      adjust the build target settings of all 44 vc2008/*.vcproj
      files within the IDE.

      See README-Visual-C++.txt for more on this change.

    o Added Query::replacefrom(): like insertfrom() but it uses
      REPLACE statements instead of INSERT.  Patch by Adrian Cornish.

    o Added support for SQL "unsigned float" columns.  Patch by
      Leonardo Lang.

    o Added "abicheck" top-level build target, which runs the
      ISPRAS ABI checker tool (http://goo.gl/e19lD) against
      a predecided "ABI-stable" version of MySQL++, comparing it
      against the current version.  This should help avoid future
      unplanned ABI breakages, as happened between 3.0.9 and 3.1.0.

      We have chosen not to revert those changes that broke the ABI,
      but instead have chosen to accept the 3.1.0 ABI as the new
      stable ABI for the rest of the 3.x series.  Running the ABI
      checker is now part of the release process, so we should not
      change the ABI again until 4.0!

    o The Query::insert() and replace() overloads that take a pair
      of iterators now work with containers that only provide forward
      iterators.  Idea by Adrian Cornish.

    o Using libtool again on Autotools systems.  It gives us
      relocatable libraries, which is needed in some linking
      situations.  Patch by Adrian Cornish.

    o VC++ release builds now have optimization enabled.  This might
      also affect other toolchains that create separate Debug and
      Release builds, if Bakefile obeys the directive for those
      systems.  (Such as, perhaps, Xcode.)  Initial patch by Matthew
      Bradbury.

    o Fixed a crash in CommandLine mechanism when the usage message is
      called up for programs that have no "extra" parameter and
      corresponding usage appendage.  Initial patch by "Crazy Pete".

    o Query::storein() now tolerates empty result sets, due either to
      DBMS failure or passing a query that never returns results,
      such as INSERT.

    o Exposed DBDriver::result_empty() as Query::result_empty().  We
      did this primarily because it was needed as a helper for the
      previous fix, but it could also be useful more broadly.

    o Added -Wextra to the pedantic build flags.

    o Fixed the "escape" manipulator so it will work with Null<>
      wrapped types.  Patch by "Kemet".

    o ssqls2parse now depends on libmysqlpp.  (It wasn't getting
      relinked when you changed the library.)

    o The configure script's test for the existence of mysql_ssl_set()
      got broken by a change in the mysql_loc.m4 test, causing it to
      always return "no" even if the platform's MySQL C API library did
      have the function.  Therefore, the SslOption could never be set.
      Fixes this bug: stackoverflow.com/questions/7794408

    o Fixed a missing a "buried headers" ifdef wrapper for
      type_info.cpp.  Patch provided by Xavier Richez.

    o We now export the DBDriver class from the MySQL++ DLL when
      building on Windows.  Client programs can now access it directly,
      instead of being able to access only the fields and members
      exposed through Connection and Query.  Fix suggested by Xavier
      Richez.

    o MinGW builds no longer require that you manually create an import
      library for the MySQL C API DLL from a .def file we provide,
      which would inevitably get outdated.  We can now link directly to
      the DLL, and rely on the MinGW linker to figure out the imports.

    o Split the -l flags out of LDFLAGS in the userman's example
      Makefiles.  They're now in LDLIBS, which causes them to be
      put after -o $(EXE) by the default GNU make rules, where they
      should be.

    o Assorted documentation and build system improvements.

    o Assorted fixes for newer GCCs.


3.1.0, 2010.06.03 (r2670)

    o Default MySQL version now 5.1, having entered GA since 3.0.9.

    o Lots of platform updates tracked, lots of warnings from newer
      compilers squished.  Most by me, some by Adrian Cornish.

    o Added Query::insertfrom(), plus associated classes SQLStream,
      NoTransactions, and the InsertPolicy hierarchy.  Also adds
      examples/ssqls6.cpp, which shows how to use this new feature.
      Thanks for this feature go to Rick Gutleber, except for
      RowCountInsertPolicy, by me.

    o Added comparison operators to tiny_int<T>.  Thanks for this patch
      go to Edward Diener.

    o Added SQLTypeAdapter::is_null().  This lets you retrieve a
      nullable column from the DB, then re-insert a value from that
      column back into the DB via a template query without explicit
      checks for null-ness; it will do the right thing now.

    o Added -f flags to lib/*.pl header file generating scripts to
      allow overriding the default limit of 25 fields for tqueries
      and SSQLSes without having to edit the file, as in previous
      versions of MySQL++.  Also added --with-field-limit option to
      the configure script so you can give both -f options at once
      during the build process.  This latter is especially useful
      for automated binary package builders.

    o The file lib/querydef.h (generated by lib/querydef.pl) now
      defines the MYSQLPP_TQUERY_MAX_PARAMETERS macro, giving the
      maximum number of parameters the functions in the generated file
      allow for template queries.  Similarly, lib/ssqls.h (generated
      by lib/ssqls.pl) defines MYSQLPP_SSQLS_MAX_MEMBERS.

    o Added ConnectionPool::safe_grab(), which pings the grabbed
      connection before returning it.  If the ping fails, we remove
      the dead connection from the pool and try again.  This doesn't
      eliminate the possibility of returning a dead connection;
      there is no protection against race conditions.  It is merely
      a best-effort attempt.

    o Added ConnectionPool::remove(Connection*), which removes a
      connection from the pool.

    o Added ConnectionPool::exchange(), which wraps remove()
      and grab().  It works like a customer support counter in a
      store: "I'm sorry, but this Connection is defective.  Can I
      have another, please?"

    o Added a feature to Transaction, where it can send a SET
      TRANSACTION ISOLATION LEVEL query before it starts the
      transaction proper, affecting the isolation level and the scope
      of that change.

    o Added ScopedConnection class.  Initial version by Joel Fielder,
      lots of changes by me.  Using it instead of explicit safe_grab()
      and release() calls on the pool in examples/cpool.cpp.

    o Added FieldNames::operator[](size_type) overloads.  This is
      necessary to correctly overload the base class versions inherited
      from std::vector.

    o FieldNames wasn't doing field-by-name matches case insentitively,
      most likely since 3.0.0 when we changed it to derive from
      std::vector.  This caused SSQLS (at least) to be case sensitive.
      Fixed this and renamed the stock.sdate field in the SSQLS
      examples to stock.sDate to test this.

    o Added Query::replace(iter, iter), on the model of existing
      insert(iter, iter).  Thanks for this patch go to David Walthour.

    o Added Query::operator!(), overriding basic_ios version so that
      "if (!query)" does the right thing.  Fixes problem report in
      thread http://lists.mysql.com/plusplus/8594

    o Query copy ctor and assignment operator now perform deeper
      copies, so you can pass Query objects around in certain ways
      that used to cause crashes.  Thanks for this patch go to Steven
      Van Ingelgem.

    o Defined *_null variants for every sql_* typedef, wrapping
      all those earlier types in Null<>.  All example programs now use
      these types instead of explicit Null<>-wrapped types.

    o Created a C++ command line parsing mechanism for the examples
      today, and for programs coming in the future.  It uses the
      platform version of getopt() if available, substituting a
      public-domain implementation that gets built into MySQL++
      itself otherwise.  It's documented in the refman -- see
      the CommandLineBase class -- but it's in the newly created
      mysqlpp::internal namespace, which means we don't promise any
      sort of ABI or API stability for it.  You're welcome to use it
      in your own programs, but expect it to change without warning.

    o Added a few missing MYSQLPP_EXPORTs to operator<<()s for stream
      manipulators, to allow their use when MySQL++ is built as a DLL.

    o Added backticks around table and column identifiers in all
      code paths exercised by dtest.  There are some others remaining,
      particularly things like Row::field_list().  Thanks for this
      patch go to Adrian Cornish.

    o Added mysqlpp::NOW() which returns a value that, when inserted
      into a SQL query, results in a call to SQL's NOW() function.
      DateTime::now() -- added in 3.0.0 -- does the same thing,
      but this is shorter and matches the SQL syntax.

    o Calling DBDriver::disconnect() twice no longer calls
      mysql_close() twice.

    o Worked around a weakness on Windows that caused problems in code
      with a connect(), disconnect(), connect() call pattern, when
      also using a named pipe to connect to the DB.  (There never
      has been a problem with this on other platforms or with other
      IPC mechanisms.)

    o Initializing a SQLTypeAdapter with a floating-point value
      equal to infinity or NaN results in SQL null if the type
      is also nullable, or 0 otherwise.  Previously, we got an
      implementation-defined string, which could give invalid SQL,
      or could give 0, a different value from NaN, infinity, or
      SQL null.  This does collapse the notions of NaN and infinity,
      but the MySQL reference manual doesn't say how you're supposed
      to preserve these differences.

    o Removed the dependency of stadapter.h on sql_types.h, just to get
      sql_tinyint*.  #including tinyint.h instead, and using equivalent
      types to what sql_types.h defines.  This is necessary because
      sql_types.h should be one of the last things included from
      mysql++.h, so that it can define sql_* equivalents for everything
      else in MySQL++, which means all those other things need to be
      #included by that point.

    o The "find MySQL++" autoconf macro (config/mysql++.m4) now
      searches for the library in lib64 subdirectories everywhere it
      also looks in lib.  We did this for the C API finder macro way
      back in MySQL++ 2.2.0, and only neglected to do it for this
      macro because it's not used by MySQL++ itself, just provided
      as a courtesy to MySQL++ users that also use autoconf.

    o Also improved the "find C API" macro (config/mysql_loc.m4)
      so it, too, is more useful in third-party projects.

    o Moved private FieldNames::str_to_lwr() method out into its
      own module, in the new mysqlpp::internal namespace, so other
      modules can use it.  Also added an overload for this new global
      method taking std::string instead of char*.

    o userman build process can now find FOP when installed from
      the standard Ubuntu/Debian package repository.

    o No longer generating refman.pdf.  It's difficult to generate
      properly on some platforms, and isn't all that useful anyway
      compared to the HTML version, which builds properly everywhere.

    o Dropped custom.h backwards-compatibility header.  (Deprecated
      over a year ago in MySQL++ 3.0.0.)

    o Fixed a bad pointer access crash in Connection::set_option()
      triggered when the option set call fails.  Thanks for this
      patch go to Kevin Regan.

    o ReconnectOption behavior now knows about a fix in MySQL 5.1.6 and
      newer that lets you set it either before the connection is up,
      or after.  If you try to set this option when MySQL++ is built
      against earlier versions of the MySQL C API, it will refuse to
      set the option because it knows the option will be reset when
      the connection comes up.

    o No longer trying to make the C API library read from a "my"
      options file before connect.  It does that by default, and
      the file is supposed to be .my.cnf anyway.

    o Reworked the load_jpeg example code for clarity, extracting
      load_jpeg_file() routine as an implementation detail and
      making that use the C++ stringstream "slurp into string" idiom
      instead of allocating a C char buffer and copying that into
      a std::string.

    o Restored support for repeating query parameters.  Apparently
      you could say things like "stuff %0 morestuff %0" in v2.1,
      but this was broken by initial 1-parameter fixes in v2.2.
      This patch reportedly lets us have both things at once, and
      improves handling of 1-parameter template queries in general.
      Thanks for this patch go to Martin Gallwey.

    o Added examples/tquery4.cpp based on test code and feedback
      from Martin.

    o Put Comparable class in namespace mysqlpp, where it should always
      have been.  Aside from being just plain wrong, it caused a
      conflict with Boost if you used its Comparable class and hoist
      them both into the global namespace.  Thanks for this patch go
      to Michael Radzewitz.

    o Fixed all the known problems with the Xcode project files.

    o Skeletal support for SSQLS v2.  Doesn't do anything useful
      yet, it just got caught up in the need to release 3.1 as-is.

    o Various enhancements to the test suite.

    o Many, many documentation enhancements.


3.0.9, 2009.02.04 (r2442)

    o It is now possible to use Null<T> objects in const context.

    o Query was emitting thousands separators when used in some
      locales.  Thanks for the fix go to Tomaž Šolc.

    o Restored support for using Query::storein() with template
      queries.  Was mistakenly removed in the 3.0.0 development
      process.

    o GCC 4.4 build fixes.  Thanks for this go to Remi Collet.


3.0.8, 2008.11.27 (r2432) The "Thanksgiving" release

    o Fixed a VC++ build error introduced in 3.0.7 in the Sun CC fix.

    o Fixed the Makefile we generate from Makefile.simple for the
      devel RPM.  The recent Bakefile upgrade changed the output so
      our munger stopped munging.

    o Changed all instances of "CREDITS" in header comments to
      "CREDITS.txt".

    o Brought ebuild file up to date with what Gentoo has been
      using for 2.3.2.


3.0.7, 2008.11.21 (r2423)

    o Fixed bug where initting a Query with a query string and then
      appending more to it with operator <<() would start overwriting
      the beginning of the buffer.  Thanks for the fix go to Chris
      Frey.

    o Added String::empty(), to parallel std::string better.

    o Added SQLTypeAdapter ctor for Null<String>, to allow SSQLS with
      NULL BLOB columns.  Thanks for this patch go to Russell Robinson.

    o Passing on "throw exceptions" flag in Query::storein() to the
      temporary Row objects it creates.  (Should have done this
      all along.)

    o All MySQL++ classes with operator[]() and at() methods now
      throw the new BadIndex exception on out of range indices now,
      unconditionally.  Before, it was a mishmash of MySQL++-specific
      mechanisms, std::range_error, and unchecked access.

    o Fixed some bugs in load_jpeg and cgi_jpeg examples that prevented
      them from working correctly on Windows.

    o Squished some warnings and incompatibilities that caused
      difficulty with Solaris CC.

    o Several minor fixes to allow building on Cygwin again.

    o Dedicated VC++ 2008 support.  (Not just a clone of VC++ 2005
      project files in a different directory.)

    o Lots of documentation improvements.


3.0.6, 2008.08.16 (r2350)

    o Several fixes to allow thread-aware build on Solaris

    o More improvements to search for Fink version of C API library.

    o Various improvements to Windows installer (install.hta)


3.0.5, 2008.08.06 (r2332)

    o Replaced install.bat with new install.hta, which has a GUI and a
      lot of embeded logic for doing The Right Thing, which we couldn't
      do in a dumb batch file.

    o Several fixes to allow it to build on Solaris 10.

    o Fixed a bug in comparison of Null<T> to T: wouldn't always give
      the right result for one particular combination of argument
      values and order of parameters to operator <().  It wouldn't
      fail all the time, either; it depended on the way the system's
      memory allocator dealt with newly allocated RAM.  The bug was
      discovered during the Solaris 10 porting effort, but it is not
      a Solaris-specific bug.

    o Split Linux-specific material out of README-Unix.txt into
      README-Linux.txt, and created README-Solaris.txt.

    o Shipping a vc2008 directory.  Populated by bootstrap script with
      copies of vc2005 files when those are newer, with the idea being
      to update them by hand by running them through VC++2008 before
      release.

    o Several fixes to VS-only examples. They hadn't been updated to
      track several of the changes in MySQL++ v3, so they wouldn't
      build OOTB at all, crashed when you did get them building, and
      emitted a lot of warnings during the build.  Cleaned it all up.

    o Autoconf now explicitly checks whether we need to link to zlib
      to link to MySQL C API library.  It used to be required, but
      lately, MySQL has been shipping the library with zlib stuff
      embedded, causing multiply defined symbol errors on some systems.

    o configure script now looks in more locations for the MySQL C API
      library, adding default locations for Fink and Solaris.


3.0.4, 2008.07.02 (r2303)

    o Fixed a few bugs in SslOption that prevented it from actually
      working.  If you've been having SSL problems since upgrading
      to MySQL++ v3, this is why!  Thanks for these patches go to
      Petteri Kiiskinen.

    o Changed type of String's internal "size" typedefs so it'll
      build without errors on 64-bit systems where these ints are
      different sizes.

    o Many user manual improvements.


3.0.3, 2008.05.11 (r2284)

    o Fixed query well-formedness handling in Query::store() and use().
      It was quietly eating these errors, confusing them with the
      no-results case.

    o Fixed examples/cpool.cpp to build without thread support.

    o No longer hiding all stdint.h typedefs inside namespace mysqlpp.

    o Fixed mysqlpp::String comparisons of empty strings against
      nonempty strings; if the empty string was on the left hand side,
      it would succeed because it was only comparing against characters
      in the empty side, which matches everything.  (Fixes bug 11588.)


3.0.2, 2008.04.13 (r2275)

    o Increased float to string conversion precision from 7 to 9 and
      double from 16 to 17 digits.  Previous values weren't enough
      near the maximum values that each can hold.

    o Replaced Query's safe bool mechanism with an override of
      basic_ios::operator void*() to avoid a conflict between the
      two mechanisms.  As the base class version isn't virtual,
      this is arguably evil, but it should be harmless in typical use.
      Besides, testing Query in bool context usually isn't the right
      thing anyway: test the result set instead.

    o Made ConnectionPool::grab() virtual.

    o Overriding ConnectionPool::grab() and release() in
      examples/cpool.cpp to show how to do connection-in-use count
      limiting.  Also, added a few more output indicator states to
      allow one to better understand program flow.


3.0.1, 2008.03.23 (r2263)

    o String objects can now be compared to mysqlpp::null directly.

    o Added a template operator== and operator!= to String, syntactic
      sugar for the existing String::compare() methods.

    o String::compare() now returns 0 ("equal") when one of the
      strings is an uninitialized String() (no refcounted buffer)
      and the other is empty.  It used to consider any initialized
      string greater than an uninitted one.  An uninitialized String
      appears empty, though, so this was incorrect.

    o Made Connection::thread_aware(), thread_start() and thread_end()
      static methods, so they can be called before you create your
      first connection.  Ditto for DBDriver versions of these methods.

    o Calling Connection::thread_start() and thread_end() in
      examples/cpool.cpp, as appropriate.  Above changes were necessary
      to make this work sensibly.

    o Made ConnectionPool::release() virtual, so your pool subclass can
      override it.

    o Added ConnectionPool::size(), so a subclass can know the current
      number of extant connections.

    o No longer single-quoting NOW() call generated for default
      init of DateTime type when building queries from SSQLS objects
      in Query::insert(), replace() and update().  The template query
      and stream interfaces of Query treated NOW() correctly already.

    o Fixed a bug that left SSQLS::table_override_ uninitted if
      you used certain of the generated ctors or set() member
      functions instead of others used by the examples.  This could
      cause a crash any time you caused SSQLS.table() to be called,
      such as when passing the SSQLS to Query::insert().

    o Minor memset bug fixed in test/uds.cpp.  Patch by Dave Jones.


3.0.0, 2008.02.29 (r2236) The "Giant Leap Forward" release

    THIS IS NOT A DROP-IN REPLACEMENT FOR MySQL++ v2.x!

    You will have to recompile your program against this version
    of the library, and you will almost certainly have to make code
    changes as well.  Please see these sections in the user manual
    for information on migrating your code to this new version:

    http://tangentsoft.net/mysql++/doc/html/userman/breakages.html#api-3.0.0
    http://tangentsoft.net/mysql++/doc/html/userman/breakages.html#abi-3.0.0

    o Added ConnectionPool class, primarily to let multithreaded
      programs share a set of Connection objects safely in situations
      where it isn't acceptable to have a Connection per thread.

    o Created examples/cpool.cpp to demonstrate this new class.

    o Added RefCountedPointer template, which provides automatic
      memory management and data sharing.  It's not intended
      for use outside of MySQL++ itself, but it's the mechanism
      behind everything below where reference counting is mentioned.
      I created the initial version of it, but Jonathan Wakely almost
      completely rebuilt it, and Joseph Artsimovich provided helpful
      commentary and advice as well.

    o Many improvements to Specialized SQL Structures (SSQLS):

      - Renamed custom* to ssqls*.  There's still a custom.h which
        #includes ssqls.h for you, but it's only intended to ease
        the transition to the new name.  It will go away in a future
        release, probably as soon as v3.1.

      - SSQLSes are finally compatible with Null<>-wrapped types.  This
        feature is based loosely on the "Waba" patch posted to the
        mailing list back in the v2.0 days, but extended to allow
        Null<T> types for key fields.  (The Waba patch only allowed
        these types in non-key fields.)

      - It's no longer necessary to define a different SSQLS for each
        different field set you use in queries.  That is to say,
        you can define an SSQLS for an entire table and store just a
        subset of the table in it now, with the other fields keeping
        default values.  Removed examples/custom6.cpp, as custom1.cpp
        can now demonstrate the same thing, implicitly.

      - An SSQLS's field order no longer has to match the order of
        fields in the result set it is populated from.

      - As a result of previous, removed sql_create_c_order_* macros;
        they have no purpose now.

      - Removed order parameters from sql_create_complete_*, which now
        gives it the same functionality as sql_create_c_names_* so
        removed the latter, too.

      - Removed "basic" variants of SSQLS creation macros.  They've
        been unofficially deprecated by dint of being all but
        undocumented and unexemplified for a very long time now.

      - It's now possible to use mysqlpp::String, Date, DateTime, and
        Time types in the key field positions in an SSQLS as they
        now support the necessary comparison interfaces.

      - If you use a floating-point data type in one of the key field
        positions, it no longer uses exact comparison logic.  Instead,
        it now does [in]equality comparisons by testing whether the
        difference between two floating-point values is less than a
        configurable threshold defaulting to 0.00001.
    
      - You can now use 'bool' type in an SSQLS.

      - Renamed _table static member variable in each SSQLS to table_
        and made it private.  There are now public setter and getter
        methods, table().

      - Added per-instance table name overriding via instance_table()
        setter.  table() getter returns static version if this is not
        set, so it's still a global setting by default.

    o You can now use mysqlpp::null as a template query parameter to
      get a SQL null.

    o Replaced template ColData_Tmpl<T>:

      - Used to have typedef ColData_Tmpl<std::string> MutableColData.
        It was used only once within MySQL++ itself, and was never
        documented as a class for end users.  This one use within
        the library was a crock, so we just replaced this use with
        std::string and removed the typedef.

      - This left just one use of ColData_Tmpl<T>, instantiating it
        with the MySQL++ utility class const_string, basically a
        clone of std::string with all the mutating features removed.
        Folded the functionality of const_string into the template,
        renamed the result to String, and deleted the const_string
        class.  It'd be a complete std::string replacement -- with
        SQL-related enhancements -- if it were modifiable, but MySQL++
        doesn't need it to be modifiable.  Yet, it's still the closest
        thing MySQL++ has to its own string type; thus the name.

      - Replaced its internal buffer management with a much more
        clever reference counted scheme.  This shows its greatest
        advantage in the return from Row::operator[](), which for
        technical reasons must return by value, not by reference
        as is more common.  This lets you pass around Strings by
        value while having the efficiency of reference semantics.
        This can be important with large return values, like BLOBs.

      - Converting String to numeric types (ints, floats...) uses a
        new, cleaner system by Jonathan Wakely.  Unless you were
        abusing weaknesses in the old system, you won't see a
        difference.  It's just more robust and flexible.

    o Redesigned SQLString:

      - It used to derive from std::string, and while MySQL++'s
        internals did use it in place of std::string, these places
        didn't take advantage of the additional features offered
        by SQLString.  So, replaced all those uses with std::string.

      - All the remaining uses are MySQL++ public interfaces that
        need to be able to accept any of many different data types,
        and we want that data to be automatically converted to a
        SQL-compatible string form.  Because it no longer has the
        parentage to be a general-purpose string type and MySQL++ has
        a new contender for that role (String), renamed SQLString to
        SQLTypeAdapter to reflect its new, limited purpose.  ("STA"
        for short.)

      - Since we don't have the std::string base class to manage the
        string buffer any more, using the same reference counted
        buffer mechanism as String.  In addition to saving code by
        not creating yet another buffer management mechanism, it means
        objects of the two classes can share a buffer when you assign
        one to the other or pass one to the other's copy ctor.

      - Added many more conversion ctors.

      - STA interfaces using the 'char' data type now treat them as
        single-character strings instead of one-byte integers, as
        does the Standard C++ Library.

      - Added mysqlpp::tiny_int interfaces to STA to replace the
        former char interfaces for those needing one-byte integers.

    o As a result of the ColData -> String redesign, removed
      Row::raw_*().  Before String copies were efficient, this
      was helpful in accessing BLOB data efficiently.  It was also
      required back when ColData didn't deal correctly with embedded
      null characters, but that reason is gone now, too.

    o Row::operator[](const char*) no longer unconditionally throws the
      BadFieldName exception when you ask for a field that doesn't
      exist.  It will still throw it if exceptions are enabled, but if
      not, it'll just return an empty String.  This was necessary to
      make the SSQLS subset and field order independence features work.

    o Similarly, Result::field_num() returns -1 when exceptions are
      disabled and you ask for a field that doesn't exist.

    o You can now use the OptionalExceptions mechanism to disable
      exceptions on const MySQL++ objects.

    o Redesigned query result classes:

      - Instead of Result deriving from ResUse, the two derive from
        a common base class -- ResultBase -- containing the bits that
        are truly the same between them.  Before, Result inherited
        several methods that didn't really make sense for "store"
        query result sets.

      - Renamed Result to StoreQueryResult and ResUse to UseQueryResult
        so it's clearer what each is for.

      - Renamed ResNSel to SimpleResult.

      - Made all SimpleResult data members private and hid them behind
        const accessor functions of the same name.

      - The result set classes all used to be friends of Connection
        for various lame reasons.  Since they are created by Query,
        and Query has a good reason for a strong relationship with
        Connection, moved Connection access out of each result set
        class into the code in Query that creates that type of result
        set object.

      - StoreQueryResult now derives from vector<Row> in addition to
        ResultBase; it used to merely emulate a vector of Rows, poorly.
        It can now dispose of the MYSQL_RESULT at the end of object
        construction, because it creates all the Row objects up front
        instead of on the fly.  And as a result of *that*, operator[]
        returns by reference instead of by value, operator -> works
        correctly on iterators, all STL algorithms work, etc., etc.

      - IMPORTANT COMPATIBILITY BREAK: because we used fetch_row()
        stuff in Result previously, it was okay to index past the
        end of the result set: you'd just get a falsy Row when you
        did this, just as happens when doing the same thing in a
        "use" query.  The simple1 and simple2 examples did this,
        so it's likely that code exists that takes advantage of this
        misfeature.  New versions of these examples show how to index
        through a StoreQueryResult without running past its end.

      - ResUse used to delay creation of its FieldNames and FieldTypes
        objects until the point of need.  This had several implications
        for thread and exception safety that we fix by just creating
        them in the ctor.  If your code is multi-threaded and was
        avoiding certain usage patterns due to crashes, it's worth
        trying your preferred way again.

      - Result sets create a few data structures to hold information
        common to all rows in that set.  The row objects need access
        to these shared data structures, so on creation each gets
        a pointer back to the result set object that creates it.
        This was efficient, but required that a result set object
        outlive any row objects it creates.  Now these shared data
        structures are reference-counted, decoupling the lifetime of
        the child row objects from their result set parent.

      - Copy operations for result sets used to actually be "moves"
        before, for efficiency.  (MySQL++ itelf only copied result
        sets in returning them by value from the query execution
        methods of Query, so this was acceptable if you didn't do
        anything uncommon with these objects.)  Reference counted
        data structures allow us to have copy semantics now without
        sacrificing efficiency.

      - You can now use Query::storein() with an STL container of Row
        objects now, instead of having to use SSQLSes.  The lifetime
        issue guaranteed a crash if you tried this before.

      - Removed a bunch of unnecessary alias methods:

        - columns() -> num_fields()
        - names()   -> field_names()
        - rows()    -> num_rows()
        - types()   -> field_types()

      - Renamed several methods for grammar reasons:

        - fields(unsigned int)      -> field(unsigned int)
        - names(const std::string&) -> field_num(const std::string&)
        - names(int)                -> field_name(int)
        - types(int)                -> field_type(int)

      - Removed several "smelly" methods:

        - purge()
        - raw_result()
        - reset_names()
        - reset_field_names()
        - reset_types()
        - reset_field_types()

    o Field class used to just be a typedef for the corresponding C
      API class.  Now it's a real C++ class providing a more MySQL++
      sort of interface, plus good OO things like information hiding
      and implementation detail abstraction.  This changes several
      things about the interface.

    o Fields class was basically a specialized std::vector work-alike
      for dealing with the C API to get access to MYSQL_FIELD objects
      and present them as contained Field objects.  New Field type
      let us replace it with "typedef std::vector<Field> Fields"

    o Major improvements to the quoting and escaping mechanisms:

      - Replaced almost all of the type-specific interfaces in manip.h
        with a single version taking STA.  The compiler can convert
        almost anything to STA without losing any information we need
        for correct quoting and escaping.  This has the side benefit
        that we can now do correct quoting and escaping for more data
        types now, including plain C and C++ string types.

      - Fixed a bug in quote_double_only manipulator for String: was
        using single quotes by mistake.

      - Escaping and quoting only works in instances where MySQL++
        can tell you're building a SQL query and are using a data type
        that requires it.  This affects many things, but the one most
        likely to cause trouble is that inserting MySQL++'s quoting
        and escaping manipulators in non-Query ostreams is now a no-op.

      - Added escape_string() member functions to Query and
        SQLQueryParms::escape_string(), and removed the global function
        of the same name.  Because these are tied indirectly to a
        Connection object, this also has the effect that escaping is
        now aware of the current default character set used by the
        database server.  There's only one case where this isn't done
        now, and that's when we're disconnected from the server.

      - Previous two items form a trade-off: if your code was depending
        on MySQL++ to get SQL escaping and it no longer happens for
        what we consider a good reason, you can build a replacement
        mechanism using these new functions.  Quoting needs no special
        support in MySQL++.

      - Removed 'r' and 'R' template query parameter modifiers,
        which meant "always quote" and "always quote and escape"
        regardless of the data type of the parameter.  There are no
        corresponding manipulators (for good reason), so the removal
        restores symmetry.

    o Created DBDriver class from code previously in Connection and
      Query to almost completely wrap the low-level MySQL C API:

      - Connection creates a DBDriver object upon connection and
        passes a pointer to it down to Query objects it creates.
        In turn, they pass the pointer on to any of their children
        that need access to the C API.

      - Nothing outside DBDriver calls the C API directly now, though
        DBDriver leaks C API data structures quite a lot, so this
        feature doesn't constitute "database independence."  See the
        Wishlist for what must be done to get to that point.

    o Completely redesigned the connection option setting mechanism:

      - There's now just a single Connection::set_option() method that
        takes a pointer to the abstract Option base class, and there is
        an Option subclass for every connection option we understand.
        Thus, type errors are now caught at compile time instead of
        at run time.

      - Replaced Connection::enable_ssl() with SslOption class.

      - Enabling data compression and setting the connection timeout
        are no longer set via parameters to Connection interfaces.
        These are now set with CompressOption and ConnectTimeoutOption.

      - Similarly, removed client_flag parameters from Connection's
        ctor and connect() method and added corresponding Option
        subclasses.  There's about a dozen, so rather than list them
        here, look for similarly-named classes in lib/options.h.

    o Added Connection::count_rows() to execute "SELECT COUNT(*) FROM
      tablename" queries for you.

    o Moved Connection::affected_rows(), info() and insert_id() methods
      to class Query, as they relate to the most recently-executed
      query, not to the connection.

    o Several method name changes in Connection:

      - client_info()   -> client_version()
      - host_info()     -> ipc_info()
      - proto_info()    -> protocol_version()
      - server_info()   -> server_version()
      - stat()          -> status()

    o Removed Connection::api_version().  It does the same thing as
      client_version().

    o Lots of changes to Date, DateTime, and Time classes:

      - If you use the default constructor for DateTime and don't
        subsequently set its year, month, day, hour, minute or second
        data members to nonzero values, it becomes the SQL function
        "NOW()" in a query string.  You can also use DateTime::now()
        as syntactic sugar for this.

      - As a result of above, had to hide all of DateTime's data
        members behind accessor functions, to keep the state of the
        object consistent.  (If it's initialized as "now" and you
        give it an explicit year value, say, it is no longer "now",
        so the setter has to clear the now-flag.)  There are getters
        and setters for year, month, day, hour, minute and second,
        all named after the member.

      - Did the same for Date and Time for consistency, even though it
        isn't technically required.

      - The sql_timestamp typedef now aliases DateTime instead of Time.

      - Renamed template class DTbase<T> to Comparable<T>.  The fact
        that it's the common base class of all date and time classes
        is irrelevant; making subclasses comparable is what it does,
        so that's what it should be named after.

      - Added a DateTime ctor taking discrete year, month, day, hour,
        minute, and second values.

      - Implicit conversion from stringish types to the date and time
        types is no longer allowed.  This is part of the "Waba"
        Null<T> patch mentioned above; allowing implicit conversions
        would break this new feature.

      - Added operator std::string and str() methods to all of these
        classes.  Adding this to the existing operator << support, you
        now have several ways to convert these objects to string form.

      - Added time_t conversion to Date and Time classes.  DateTime
        already had it, since it's more legitimate to convert time_t
        to DateTime, but you could already "slice" it with something
        like Time(DateTime(time(0))) so there's no point pretending
        you can't get from time_t to Date or Time.  Might as well
        legitimize it.

    o Improved tiny_int class:
        
      - Turned it into a template parameterized on the value type so
        you can get both signed and unsigned TINYINTs

      - Changed the sql_tinyint and sql_tinyint_unsigned typedefs to
        use mysqlpp::tiny_int<VT> instead of raw chars

      - Added a bool conversion ctor and operator, and typedef'd it
        to sql_bool and sql_boolean to match MySQL server behavior

    o Added many more sql_* typedefs.  We now have a typedef for every
      type the MySQL server knows about, including those it supports
      just for compatibility with other database servers.

    o Changed the sql_*int* typedefs to use integer types of the same
      size as the MySQL server.  (Run test/inttypes.cpp to test it.)

    o Added copy ctor and assignment operator to Row.

    o Row::operator[]() takes int now instead of unsigned int.
      This finally (!) makes it possible to say row[0] without the
      compiler giving an ambiguous overload error.

    o Changed all uses of row.at(0) in the examples to row[0]

    o Added operator[] to all classes that only had at().

    o Query now automatically resets itself unless the query fails
      or you're using template queries.  In either case, the contents
      of the query's internal buffers are considered precious,
      either for debugging, or future queries.  Except when using
      template queries, this means you may be able to avoid calling
      Query::reset() entirely.  It's still safe to call reset()
      as before, just unnecessary most of the time.

    o Removed reset_query parameter from all Query methods.  It was
      almost completely broken before, and above change does what
      was really wanted to begin with.

    o Query::store_next() and Result::fetch_row() no longer throw
      the EndOfResults and EndOfResultSets exceptions; these are not
      exceptional conditions!  These methods simply return false now.

    o Removed examples/usequery.cpp: there's no essential difference
      between what it did and what examples/simple3.cpp does now as
      a result of the previous change.

    o Added Query::exec(void), paralleling Query::execute(void).

    o Removed Query::preview().  The most direct replacement is str(),
      which has always done the same thing.

    o You can now insert a Query object into an ostream to get a copy
      of the built query.  This means Query::str() is only necessary
      when using template queries.

    o Removed overloads of Query::execute(), store(), and use()
      that take const char*.  It was redundant because const char*
      converts implicitly to STA, for which overloads already exist.

    o Renamed Query::def to Query::template_defaults to make its
      purpose clearer.

    o Query::error() now returns const char*, not a std::string by
      value.  There's no point in making a copy of the error string.
      The method is now const as well, as it doesn't change the
      Query object.

    o Added Query::errnum(), which just wraps Connection::errnum().

    o Added error number parameters and accessor functions to BadQuery,
      ConnectionFailed and DBSelectionFailed exceptions, to preserve
      the state of Connection::errnum() at the point of the exception,
      so you don't have to rely on this value remaining unchanged
      during the exception throw process.  All places that use these
      exceptions now include this value where possible.  Thanks for the
      initial patch go to Jim Wallace.

    o Removed Lockable mechanism from Connection and Query; it was
      conceptually flawed.  See the new user manual chapter on
      threading for advice on using MySQL++ safely without locking.
      There is mutex locking now in ConnectionPool, but that's it.

    o Connection::query() now takes an optional query string, allowing
      the returned Query object to start off with a value.  Especially
      useful when the query string is static, either because it's
      a simple query or because it's a template.  You can now build
      chains like "if (conn.query("CREATE INDEX ...").exec()) { ..."

    o Added Connection::thread_aware(), thread_end(), thread_id()
      and thread_safe().  See user manual's threading chapter for
      explanations.

    o Renamed "success" data members in Connection, Query and
      SimpleResult (neé ResNSel) to "copacetic_", making them private
      if they weren't before.  This better reflects their actual
      use, which isn't to say that there has necessarily been actual
      success, but rather that everything's okay with the object.

    o Removed success() member functions from above classes.  All can
      be tested in bool context to get the same information.

    o Replaced all operator bool()s in MySQL++ classes with safer
      alternatives.  See http://www.artima.com/cppsource/safebool.html
      Thanks to Jonathan Wakely for much helpful commentary, advice,
      and code used in these mechanisms.

    o Decoupled Connection::copacetic_ from Connection::is_connected_.
      It is now possible for the object to be copacetic without being
      connected.  However, if it tries to connect and fails, then
      it is not copacetic.  If it is copacetic and not connected, it
      means we haven't even tried to connect yet, a useful distinction.

    o Collapsed Connection's host, port, and socket_name down into
      a new combined 'server' parameter which is parsed to determine
      what kind of connection you mean.  These interfaces are still
      compatible with v2.3 and earlier up through the port parameter.
      There are differences beyond this.

    o Added TCPConnection, UnixDomainSocketConnection and
      WindowsNamedPipeConnection subclasses for Connection giving
      simpler construction and connect() method interfaces for
      instances where you know what kind of connection you want at
      compile time.

    o Changed Connection::ping() return value from int to bool.

    o Renamed NullisNull to NullIsNull -- capital I -- and similar for
      NullisZero and NullisBlank.

    o It's now a compile-time error to try to convert a MySQL++
      representation of a SQL null to any other data type, rather
      than a run-time error as in previous versions.  Removed
      BadNullConversion exception as a result.

    o Way back in v1.7.x we used the BadQuery exception for all kinds
      of exceptional conditions, not just bad queries.  Replaced
      most of these in v2.0.0 with new dedicated exceptions, but a
      few remained:
      
      - Errors that occur during the processing of a "use" query after
        the query itself executes correctly now throw UseQueryError.
        It's not a "bad query", because the query executed
        successfully.  It just choked during subsequent processing,
        so it's a different exception.  Thanks for this patch go to
        Jim Wallace.

      - Replaced BadQuery exceptions thrown in Row constructor due
        to bad ctor parameters with new ObjectNotInitialized exception
        This is also Jim Wallace's work.

    o The examples now all use getopt() type command line options
      instead of positional options.  This makes it possible to
      pass options in any order, leave at their default options that
      used to be in the middle of the sequence, and offer different
      subsets of options for different programs.  Also allows for
      special internal-use options, like -D passed by dtest to let
      examples change their behavior when run under dtest to produce
      only predictable output.

    o Split old libutil functionality into two modules, one holding
      all the "print data" functions, and another holding all the
      command line parsing stuff.  This makes it easier for newbies
      to ignore the command line stuff, treating it like a black box.
      The wish to understand the "print data" routines is much more
      common, so the two needed to be disentangled.

    o Renamed examples' libutil to libexcommon.

    o Removed connect_to_db() libutil function.  It combined command
      line parsing, which users don't care about, with database
      connection establishment, which they do care about.  Now the
      examples just call out to libexcommon to parse the command
      line, and use the values they get back to explicitly make the
      connection, so it isn't hidden.

    o Removed cchar and uint typedefs.

    o Redesigned dbinfo example's output to be easier to read.

    o Fixed an output formatting bug created in 2.3.0 that caused the
      tabular output from examples to not line up.

    o Renamed examples/tquery.cpp to tquery1.cpp.  Created tquery2.cpp
      to demonstrate passing parameters via a SQLQueryParametrs object
      instead of discretely.  Created tquery3.cpp for testing unquoted
      template parameters, such as integers.

    o Renamed fieldinf1.cpp example to fieldinf.cpp, and simplified
      its output so it can be part of the dtest sequence.

    o Renamed examples/xaction.cpp to transaction.cpp.  It created too
      much cognotive dissonance whenever thinking about both it and
      lib/transaction.cpp.

    o Added examples/deadlock.cpp, to test handling of exceptions due
      to server-side transaction deadlock detection.  Also added
      code to resetdb to create a table needed to test this.
      Initial version created by Jim Wallace to test the value of
      all his BadQuery exception work, with reworking by me.

    o Greatly expanded dtest suite.  Primary change is that we now
      have a handful of unit tests, where in v2.3.2 we only tested
      a subset of the examples.  Still very low coverage ratio,
      but it's a big improvement.

    o Optimized #includes, especially in lib/*.h to reduce
      dependencies and thus compile time when one of these changes.

    o Fixed a typo in RPM filename generation that prevented -devel
      RPM from recognizing that the corresponding MySQL++ library
      RPM was installed.

    o RPM spec file improvements by Remi Collet.

    o Renamed NO_LONG_LONGS to MYSQLPP_NO_LONG_LONGS to avoid a risk
      of collision in the global macro namespace.
    
    o First cut at Xcode2 project support.  Testing needed!

    o Debug build of library on VC++ and Xcode have a _d suffix now
      so you can have both versions of the library installed without
      conflict.

    o Moved the VC++ 2003 project files into a new vs2003 subdirectory
      because there are so many of them.  Also created vs2005
      subdirectory for VC++ 2005 and 2008 compatible project files.
      2005 makes an even bigger mess of the directory containing
      the .sln file, so the incentive is bigger.  Plus, we have to
      disable several things to get VC++ 2003 to build MySQL++ now,
      so we need a special 2005+ version of the project files for a
      complete build, if the user has one of the newer compilers.

    o ...plus dozens of small bug fixes and internal enhancements,
      many documentation improvements, and expansion of support for
      newer operating systems and compilers.


2.3.2, 2007.07.11 (r1669)

    o Previous release's const_string change caused more problems
      than it fixed.  This release contains the real fix. :)

    o New Connection::set_option() handling deals with the multi
      statements option correctly again.  examples/multiquery now
      runs again as a result.

    o Added new unit testing script, called dtest.  See the
      HACKERS file for details.  (This tool caught the previous
      two problems!)

    o Squished a GCC pedantic warning.  Thanks for the patch go to
      Andrew Sayers.


2.3.1, 2007.07.10 (r1659) The "After the Fireworks" release

    o const_string objects now keep a copy of their data, not
      just a pointer to it.  This is less efficient, but necessary
      to allow SSQLS to work with BLOBs.  Without this, we were
      seeing segfaults due to accessing freed memory pointed to
      by the const_string, because the underlying object went
      out of scope.

    o Fixed many more potential embedded null handling problems
      in manip.h.

    o MySQL++ can now optionally reference MySQL C API headers as
      being in a mysql subdirectory, a common thing on *ix systems,
      by defining MYSQLPP_MYSQL_HEADERS_BURIED before #including
      mysql++.h.

    o Restored ColData_Tmpl<T>::get_string(), removed in v2.3.0,
      along with warnings in the docs saying why you don't want
      to use it, and what your alternatives are.

    o VC++ and MinGW builds now define the HAVE_MYSQL_SSL_SET
      macro, which lets you use the C API's SSL features.
      This assumes your C API library does actually have these
      features enabled, which is the case with the official binary
      releases on Windows.  (Builds on *ix systems continue to
      test for these features at configure time.)

    o Fixed simple examples-only Makefile generation, for RPMs.


2.3.0, 2007.07.02 (r1645)

    o Added Query::for_each() and Query::store_if() methods
      proposed by Joel Fielder, and added examples for each.

    o It's now possible to store BLOB data in an SSQLS.  It's not
      foolproof, so added a section to the user manual (5.9) to
      document the method.  Also, changed examples/cgi_jpeg to use
      this new mechanism, instead of the ugly "raw row data" method
      it used to use.

    o Revamped Connection::set_option() handling.  These options
      used to be queued up, and applied only just before actually
      establishing the connection.  This made error reporting less
      helpful because the diagnostic was separated from the cause.
      Plus, the error messages were misleading to begin with.  Now,
      set_option() takes effect immediately if the connection is not
      yet up (excepting one special option that can actually be set
      after the connection is up) and issues better diagnostics when
      it detects errors.

    o Connection::connect() used to set a few options in such a
      way that the user couldn't override them.  Now it's smart enough
      to set them with the desired default values only when we see
      that the user hasn't given them other values.

    o SQLString can now be initialized from a mysqlpp::null,
      giving a "NULL" string.  This is useful for template queries.
      Patch by Michael Hanselmann.

    o resetdb error message about mixing library and header version
      numbers is now more explicit.

    o Changed BadConversion exception's "what" message text to be
      more like the other exceptions.  The inconsistency lead one
      to incorrectly copy-paste code from another exception handler,
      expecting it to behave the same way.  Now it does.

    o Added Row::raw_size(), as a shortcut for Row::at().size().

    o ssqls-pretty now detects when it's being run from within
      the MySQL++ distribution tree and gives a different -I flag
      to the compiler, so that it picks up the distribution headers
      instead of those that may be on the system already.

    o The quote manipulator now works for char[] correctly.
      Thanks for this patch go to Andrew Sayers.  (It's always
      worked for char*, but C++ doesn't consider that to be the
      same type, so it used the generic quote handling path,
      which doesn't do anything for char[].)

    o Fixed a build bug on older Solaris versions where the
      test for the C API library was erroneously failing, stopping
      the configuration process.

    o Simplified mysql_shutdown() level argument detection.
      Already had to do a version number ifdef check for the
      Windows case, so there's really no point to doing it with
      autoconf on Unixy platforms.  Moved version number check
      into lib/connection.cpp, and nuked the separate autoconf and
      Windows tests.

    o Removed dependency of sql_types.h on myset.h and (indirectly)
      datetime.h.  Now we only define sql_* typedef aliases for those
      MySQL++ types if the headers are included before sql_types.h.

    o Fixed a typo in one of the storein_sequence() template
      overloads, which is apparently rarely (or never?) used, because
      no one reported the compiler error you'd get if you tried.

    o Fixed a few more embedded null handling problems.

    o ColData used to keep two copies of all data it held.
      Now it keeps just one.

    o Fixed install.bat script to track the unified Bakefile change
      and the lack of separate debug and release builds under MinGW.

    o Yet another STLport + Query memory leak fix.

    o Squished a warning in newer GCCs having to do with identifier
      shadowing.  Patch by Jonathan Wakely.

    o Fixed a null-termination bug in Query::parse().  If you
      somehow constructed a query string without a terminating null
      character, then tried to parse it as a template query, it could
      walk off the end of the string.  Patch by Worster Chen.

    o Removed MYSQLPP_EXPORT tag from FieldNames and FieldTypes
      class declarations, as this can cause problems in programs
      that use vector<string> in VC++.  It has to do with multiply
      defined templates, since these classes derive from that
      template, and VC++ can't resolve the conflict without help.
      Since these classes aren't actually used outside the library,
      this shouldn't cause a problem.  Patch by Nils Woetzel.

    o Partial fix to Doxygen PDF build on RHEL4 and 5.  Needs
      hand-coaxing to complete successfully on RHEL4, and doesn't
      yet work at all on RHEL5.

    o Shortened the "no*" options to the bootstrap script, so that
      the usage message fits on a single line.

    o Added "nodoc" bootstrap script option, for disabling the
      documentation build during the dist target build.  Allows for
      building binary RPMs on CentOS 5.0, where doc building is
      currently broken.

    o Removed the updel example program.  It was kind of silly,
      and if you were to rewrite it today, you'd use for_each() anyway.

    o Lots of documentation improvements.


2.2.3, 2007.04.17 (r1538) The "Tax Day" release

    o Previous version left examples/vstudio/* out of the tarball
      by accident.

    o Improved generation of RPM temporary build directory path
      name generation.  Was using a hacked variant of the Fedora
      Packaging Guidelines' second best choice.  Now we're using
      the choice they recommend most highly, without changes.

    o Removed unnecessary resources from vstudio/wforms example.

    o Minor URL fix in refman


2.2.2, 2007.04.13 (r1526) The "Nervousmaking Friday the 13th" release

    o More small fixes to embedded null handling in Query.

    o Fixed a bug in single-parameter template query handling.

    o Added tquery example, to demonstrate proper use of template
      queries.  Previously, resetdb was the only exemplar, and
      it wasn't really suited for that.  This example also tests
      the previous item.

    o Added examples/vstudio/mfc, allowing us to improve the way
      we demonstrate Unicode handling.  Old way wasn't realistic.
      On *ix, people will depend on the terminal code to handle
      UTF-8.  On Windows, users are almost certain to be writing
      a GUI program, which requires different Unicode handling
      than the old examples showed.

    o Removed explicit Unicode conversion stuff from command line
      examples, and reworked the Unicode chapter in the user
      manual.
    
    o Added examples/vstudio/wforms to show integration with
      C++/CLI and Windows Forms.  Documented this in README.vc.

    o Rewrote load_file and cgi_image examples to be more
      useful, renaming them to load_jpeg and cgi_jpeg along
      the way.  Also, resetdb now creates a second table in the
      sample database for these two examples' use.  Also, added
      examples/logo.jpg to the distribution as sample data for
      these examples.

    o Limited the ostream base class casting stuff in Query to
      VC++ 2003, which is the only platform that really needed it.
      VC++ 2005 emits a warning with that hack in place, and on
      other platforms it's just replicating work that the compiler
      does already.

    o Added library version information to main library target
      so that systems that version shared libraries work as
      expected.  Thanks for this patch go to Jack Eidsness.

    o Merged much of the diffs between Remi Collet's RPM spec file
      into the official one.

    o Reorganized the doc subdir a bit.  Generated HTML is now all
      under doc/html instead of scattered under other subdirs,
      and renamed doc/README.mysql++ to doc/README.manuals.

    o Improvements to top-level manual building make targets:
      manuals now only rebuild at need, it's easier to request
      a rebuild of all manuals, and we force a rebuild attempt
      before building the distribution tarball so we don't ship
      outdated manuals.

    o Added ability to run examples under gdb using exrun,
      using same mechanism as we currently have for valgrind.
      Thanks for this patch go to Michael Hanselmann.

    o Added "Important Underlying C API Limitations" chapter to the
      user manual, to cover problems we keep seeing on the
      mailing list that are the result of ignorance of the way
      libmysqlclient behaves, not bugs MySQL++ is really in a
      position to fix.


2.2.1, 2007.02.28 (r1433)

    o Fixed the new localtime() alternative selection code
      for VS2003 and various uses of STLport.

    o No longer inserting a null character into the query stream
      on calling one of the preview() functions.  This was harmless
      in v2.1, which used C strings more extensively, but began
      causing problems in v2.2 due to its wider use of C++ strings.

    o Fixed a bug in the Connection copy ctor where it didn't
      completely initialize the object.

    o Optimized Query::preview_char() a bit.  Patch by Jonathan
      Wakely.

    o Reordered directory list used by autconf when locating the
      MySQL C API library.  The list is now ordered with the
      most likely locations for the library first, so we're less
      distracted by incorrect libraries.  This fixes a specific
      build error under RHEL4 with recent versions of MySQL 5.0.


2.2.0, 2007.01.23 (r1417)

    o ColData, const_string, and SQLString can now be constructed
      with an explicit length parameter.  Furthermore, Query
      class's execute(), store() and use() call chains terminate
      in a version taking an explicit length parameter, instead
      of one taking a simple C string.  Together, this means
      that it's now easier to handle data from the SQL server
      containing nulls.  The library is almost certainly not yet
      capable of handling embedded nulls in all cases, but this
      is a big first step towards that.

    o Can now construct a DateTime object from a time_t, and
      convert a DateTime back to a time_t.  Patch by Korolyov Ilya.

    o Changed the way we're handling exported functions in the
      Windows DLL case so that it works more reliably under MinGW.

    o Added proper copy semantics to Connection, so that you get a
      new connection with the same parameters, not just a bitwise
      copy of the object.

    o Using an explicitly thread-safe variant of localtime() for
      time conversions where one is available.

    o Removed ListInsert template from myset.h.  This wasn't used
      within the library, and was never documented, so I'm betting
      that no one actually uses it.

    o Result::copy() was not copying the exception flag in
      all cases.  Fix by Steven Van Ingelgem.

    o Added exrun shell script and exrun.bat files to distribution,
      to avoid linkage errors when running the examples while
      you still have an older version of MySQL++ installed.

    o Renamed MYSQLPP_LIB_VERSION to MYSQLPP_HEADER_VERSION, as
      what it really encodes is the version number in the mysql++.h
      file you're using, not the actual library version number.

    o Added mysqlpp::get_library_version(), which returns the
      library version number at build time.  Between this and
      the header version constant, you can check that you're not
      mixing MySQL++ header and library versions.

    o resetdb example uses these new version number affordances to
      double-check that you're not mixing libraries and headers
      from different versions.  This happens easily unless you
      take care of it (such as by using exrun) when you have one
      version of MySQL++ installed and you're trying to build and
      test a new version without blowing away the old one first
      or overwriting it.

    o No longer using recursive Makefiles on Unixy platforms
      or split lib + examples project files on VC++.  Everything is
      handled by a single top-level Makefile or project file, which
      is simpler for the end user, and makes better dependency
      management possible.

    o When looking for the MySQL C library on systems using
      autoconf, looking in .../lib64 wherever we are also looking
      in .../lib.

    o RPM build process no longer depends on Bakefile.  It means
      you have to build the examples when building an RPM even
      though they're never used within the RPM, but it's a better
      tradeoff in my opinion.

    o Updated include and library paths on Windows to reflect
      changes in the most recent MySQL installers.

    o Merged lib/defs.h and lib/platform.h into new file,
      lib/common.h.  Just cleans up the library internals.

    o Fixed build errors on Windows due to recent changes in MySQL.

    o Fixed a few memory leaks and double-deletes in Query class.

    o Fixed compatibility with STLPort's string implementation.
      Patch by dengxy at cse.buaa.edu.cn.

    o Fixed a compatibility problem between Set<> template and
      SSQLS.  Patch by Korolyov Ilya.

    o Fixed build bug in SQLQueryParms due to a character
      signedness issue on PowerPC with GCC.  Patch by Michael
      Hanselmann.

    o ~Transaction() can no longer throw exceptions.  It'll just
      quietly eat them, to avoid program termination.  Fix
      suggested by Alex Burton.

    o Fixed thread safety testing in autoconf case, accidentally
      broken during v2.1.0 development cycle.

    o Using Doxygen 1.5.1 to generate documentation.


2.1.1, 2006.04.04 (r1289)

    o MinGW and Cygwin will now build and link to mysqlpp DLLs.

    o Fixed bug in Query, causing it to initialize the "throw
      exceptions" flag incorrectly.  Thanks for this patch go to
      Joel Fielder.

    o Added -v flag for custom.pl script, which turns off the
      multiply-defined static variable fix.  Needed for VS 2003,
      which doesn't support variadic macros.  Also, added
      a diagnostic to detect the need for the -v flag, and
      suppressed the test for this feature in examples/util.cpp.


2.1.0, 2006.03.24 (r1269)

    o Converted automake and makemake files to their equivalents in
      Bakefile format.

    o Added the Transaction class, which makes it easy to use
      transaction sets in MySQL++.

    o Added xaction example to test new Transaction class.

    o Resetdb example now creates its example table using the
      InnoDB storage engine, in order to test the new transaction
      support.  Resetdb also declares the table as using UTF-8
      text; this doesn't change anything, but it does correctly
      document what we're doing.

    o Added sql_types.h header, containing C++ typedefs
      corresponding to each MySQL column type.  Using those new
      types in the type_info module, and in the SSQLS examples.

    o Replaced the way we were handling the template query
      version of Query member functions, to allow an arbitrary
      number of template query parameters.  By default, we
      now support 25 parameters, up from the old limit of 12.
      It's now possible to change just one number, run a script,
      and have a new limit.

    o Connection class does a better job of returning error
      messages if you call certain member functions that depend
      on a connection to the server before the connection is
      established.

    o Updated libmysqlclient.def for newer versions of MySQL.  (Fixes
      build errors having to do with mysql_more_results() and
      mysql_next_result().

    o Replaced final use of strcpy() with strncpy().

    o custom.pl now runs without complaint in strict mode, with
      warnings turned on.  Thanks for this patch go to "Waba".

    o Fixed a bug in custom.pl where incorrect code would be
      generated for some SSQLS set() methods.  Thanks for this
      patch go to "Waba".

    o SSQLS structures now support long and unsigned long fields.
      Thanks for this patch go to "Waba".

    o It's now possible to put SSQLS definitions in a header
      file used by multiple modules in a program without
      getting multiple static member definition errors.  See the
      documentation for details.  Thanks for this patch go to
      Viktor Stark.

    o Moved the definition of the 'stock' SSQLS out of the
      custom*.cpp example files and into a new stock.h file.
      Also, #including that file in the util module to test out
      the new SSQLS multiple static definition fix.

    o Using all of the digits of precision guaranteed by the
      IEEE 754 spec when stringizing floating point numbers
      to build queries.  Previously, we would use the platform
      default, which can be as few as 6 digits.

    o Removed lib/compare.h.  Not used within the library, never
      documented, and nobody seems to want to defend it.


2.0.7, 2005.11.23 (r1147)

    o Added explicit mysqlpp namespace qualifiers to generated code in
      custom*.h so you can use SSQLS in places where it doesn't make
      sense to say "using namespace mysqlpp" before the declaration.
      Also updated some of the examples to not have this "using"
      declaration to make it clear to users that it isn't needed, if you
      want to use explicit namespace qualifiers as well.  Thanks for
      this patch to Chris Frey.

    o Removed an apparently useless unlock() call from ResUse; there is
      no nearby lock() call, so if this unlock() is in fact necessary,
      it shouldn't be here anyway, because the two calls should be
      nearby each other.  Thanks for this patch to Chris Frey.

    o Fixed Query ostream initialization bug affecting SunPro CC (at
      least).  While this bug violates the Standard, it doesn't affect
      many real compilers because they don't enforce this rule.  Fixed
      by Chris Frey.

    o Previously, we only used the C99 style "long long" support when
      building under GNU CC.  This is now the default.  This should
      allow the code to work under SunPro CC.

    o Added another dynamic cast needed for proper Query ostream
      subclass overloading under VC++.  (7.1 at least...)

    o Detecting whether MySQL is built with SSL support on platforms
      using autotools.  Needed on some old Sun systems, for instance.
      Thanks for this patch to Ovidiu Bivolaru.

    o Fixed a potential memory bug in ColData's conversion to SQL null.

    o Many minor packaging tweaks.  (README clarifications, file
      permission fixes, better adherence to GNU packaging standards,
      etc.)

    
2.0.6, 2005.09.28 (r1123)

    o Fixed makemake.bat so it works on cmd.exe, not just 4NT.

    o Documentation fixes.


2.0.5, 2005.09.13 (r1114)

    o Visual C++ build now requires GNU make.  It is tested to work
      with either the Cygwin or the MinGW versions.  The previous
      version of MySQL++ used nmake.  This change enabled the
      following features:

        o Debug and Release versions are both built into
          separate subdirectories.

        o Dependency tracking for release version works
          correctly now.  (Previously dependencies worked
          only for debug version.)

        o 'make clean' removes release version binaries
          in addition to debug versions.

    o MinGW makemake support updated to support new release/debug
      subdirectory system.  This is probationary support, since
      this code currently can't be built as a DLL.  As a result,
      it is no more useful than the Cygwin version, for licensing
      reasons.

    o Several fixes to allow building on Solaris 8.  These fixes may
      also help on other SVR4-derived systems.

    o Removed Borland C++ makemake support, because this version
      of the library does not work completely, and there seems
      to be almost no user interest in fixing it.
      
    o Clarified "Handling SQL Nulls" section of user manual's
      Tutorial chapter.


2.0.4, 2005.08.29 (r1076)

    o Made mysql_shutdown() second parameter autoconf check less
      sensitive to compiler pedantry.

    o VC++ library Makefile is now smart enough to re-create the
      import library, if it is deleted while leaving the DLL alone.

    o Added libmysqlclient.def to tarball.

    o Reworked most of the top-level README* files.

    o Renamed LGPL file to LICENSE.


2.0.3, 2005.08.25 (r1060)

    o Visual C++ makemake system updated to build both debug and
      release versions of library DLL.

    o Fixed bug in simple1 example that caused crashes on Windows.

    o Doing UTF-8 to ANSI text translation in simple examples now.

    o Previous two releases built libmysqlpp with wrong soname on
      autotools-based systems.  Fixed.


2.0.2, 2005.08.18 (r1050)

    o Fixes to makemake system for cmd.exe.

    o Fixed the case where the system's C++ library includes an slist
      implementation in namespace std.


2.0.1, 2005.08.17 (r1046)

    o Added new simple1 example, showing how to retrieve just one
      column from a table.  Old simple1 is now called simple2, and
      simple2 is likewise shifted to simple3.

    o Added custom6 example, showing how to do the same thing with
      SSQLS.

    o Updated user manual to cover new examples.

    o Was accidentally shipping Subversion crap with tarball.  Fixed.


2.0.0, 2005.08.16 (r1031) The "Excess Hair Removal" release

    THIS IS NOT A DROP-IN REPLACEMENT FOR MySQL++ v1.7!

    At minimum, you will have to recompile your program against
    this library.  You may also have to make code changes.
    Please see the "Incompatible Library Changes" chapter of
    the user manual for a guide to migrating your code to this
    new version:

        http://tangentsoft.net/mysql++/doc/html/userman/breakages.html

    o The library's shared object file name (soname) scheme has
      changed.  (This mainly affects POSIX systems.)
      
      The soname for the last 1.7.x releases of MySQL++ was
      libmysqlpp.so.4, meaning the fourth version of the library's
      application binary interface (ABI).  (The first ABI version
      in this scheme was that provided by 1.7.9.)  MySQL++
      2.0.0's soname is libmysqlpp.so.2.0.0.  Since the dynamic
      linker setup on some systems will create a symlink to
      that file called libmysqlpp.so.2, it's possible that this
      library could be confused with that for MySQL++ 1.7.19
      through .21, which also used this number.  Do not install
      this library on a system which still has binaries linked
      against that version of the library!

      The new scheme is {ABI}.{feature}.{bug fix}.  That is,
      the first number changes whenever we break the library's
      binary interface; the second changes when adding features
      that do not break the ABI; and the last changes when the
      release contains only internal bug fixes.  This means
      that we will probably end up with MySQL++ 3.0 and 4.0 at
      some point, so there will be further soname conflicts.
      Hopefully we can put these ABI changes off long enough
      to avoid any real problems.

    o autoconf now installs headers into $prefix/include/mysql++,
      instead of $prefix/include.  If you were using the
      --includedir configure script option to get this behavior
      before, you no longer need it.

    o Linux binary RPMs will henceforth include only the
      libmysqlpp.so.X.Y.Z file, and create any short names
      required, to allow multiple versions to be installed at
      once.  Currently, you cannot install two MySQL++ library
      RPMs at once, because they both have /usr/lib/libmysqlpp.so.X,
      for instance.

    o Replaced the Visual C++ and Borland C++ project files with
      a new "makemake" system, which creates Makefiles specific
      to a particular toolchain.  This new mechanism also supports
      MinGW and generic GCC-on-*ix.  This was done partly to reduce
      the number of places we have to change when changing the
      file names in MySQL++ or adding new ones, and partly so we're
      not tied to one particular version of each of these tools.

    o VC++ Makefiles create a DLL version of the library only
      now, so there's no excuse for LGPL violations now.
      This same mechanism should make DLL builds under other
      Windows compilers easy.

    o Added Connection::enable_ssl(), which enables encrypted
      connections to the database server using SSL.

    o Connection::create_db() and drop_db() now return true on
      success, not false.

    o Connection::create_db() and drop_db() use Query::exec()
      now, for efficiency, rather than Query::execute().

    o Removed Connection::infoo().  Apparently just there to
      save you from a typo when calling the info() method, since
      it was a mere alias.

    o Renamed Connection::real_connect() to connect(), gave
      several more of its parameters defaults, and removed old
      connect() function.  Then changed user manual and examples
      to use new APIs.

    o Replaced Connection::read_option() with new set_option()
      mechanism.  The name change matches the method's purpose
      better.  Functional changes are that it returns true on
      success instead of 0, it supports a broader set of options
      than read_option() did, and it enforces the correct option
      argument type.

    o You can now call Connection::set_option() before the
      connection is established, which will simply queue the option
      request up until the connection comes up.  If you use this
      feature, you should use exceptions, because that's the only
      way an option setting failure can be signalled in this case.

    o Removed query-building functions (exec*(), store*(),
      use()) from class Connection, and moved all the implementation
      code to class Query.  Query no longer delegates the final
      step of sending the query to the database server to
      Connection().

    o Added Connection::enable_ssl(), for turning on SSL support on
      a connection.

    o Extracted exception disabling mechanism out of the many
      classes that had the feature into a new OptionalExceptions
      base class, which all classes having this feature now
      derive from.  Also, removed all per-method exception
      handling flags.  Finally, added NoExceptions class.  With
      all of these changes, there is now a common way to disable
      exceptions with fine granularity on all objects that
      support the feature.

    o All custom MySQL++ exceptions now derive from the new
      Exceptions class.  This regularizes the exception interface
      and allows you to use a single catch() block if you want.

    o The "throw exceptions" flag is passed from parent to child
      in all situations now.  (Or if not, please report it as
      a bug.) This fulfills a promise made in the v1.7.9 user
      manual, with the cost being that some programs will see
      new exceptions thrown that they're not expecting.

    o Added a bunch of new exception types: BadOption,
      ConnectionFailed, DBSelectionFailed, EndOfResults,
      EndOfResultSets, LockFailed, and ObjectNotInitialized.
      Some of these replace the use of BadQuery, which in v1.7.x
      was a kind of generic exception, thrown when something more
      specific wasn't available.  Beware, this means that programs
      may start crashing after recompiling them under v2.0 due to
      uncaught exceptions, if they were only trying to catch BadQuery.

      There are additional instances where the library will
      throw new exceptions.  One is when calling a method that
      forces the internals to use an out-of-bounds index on a
      vector; previously, this would just make the program
      likely to crash.  Another is that the library uses the
      BadFieldName exception -- created in v1.7.30 -- in more
      apropos situations.

    o Renamed SQLQueryNEParms to BadParamCount, to match naming
      style of other concrete exception types.

    o Extracted lock()/unlock() functions from Connection and
      Query classes into a new Lockable interface class.  Locking
      is implemented in terms of a different class hierarchy, Lock,
      which allows multiple locking strategies with a single ABI.

    o Removed ResUse::eof().  It's based on a deprecated MySQL
      C API feature, and it isn't needed anyway.

    o Removed arrow operator (->) for iterator returned by Fields,
      Result and Row containers.  It was inherently buggy, because
      a correct arrow operator must return the address of an
      object, but the underlying element access functions in these
      classes (e.g. at()) return objects by value, of necessity.
      Therefore, this operator could only return the address of
      a temporary, which cannot be safely dereferenced.

    o Returned Row subscripting to something more like the
      v1.7.9 scheme: there are two operator[] overloads, one for an
      integer (field by index) and another for const char* (field
      by name).  lookup_by_name() has been removed.  Because row[0]
      is ambiguous again, added Row::at() (by analogy with STL
      sequence containers), which always works.

    o Collapsed two of the Row::value_list*() overloads into
      two other similar functions using default parameters.
      This changes the API, but the removed functions aren't
      used within the library, and I doubt they are used outside,
      either.

    o Merged RowTemplate into Row.

    o Merged SQLQuery class into Query class.

    o Query is now derived from std::ostream instead of
      std::stringstream, and we manage our own internal string
      buffer.

    o Moved SQLParseElement and SQLQueryParms into their own
      module, qparms.

    o Added multiple result set handling to Query.  MySQL 4.1
      and higher allow you to give multiple SQL statements in a
      single "store" call, which requires extensions to MySQL++
      so you can iterate through the multiple result sets.  Also,
      stored procedures in MySQL 5.0 reportedly return multiple
      result sets.  Thanks for the initial patch go to Arnon Jalon;
      I reworked it quite a bit.

    o Query::storein*() now supports more varieties of the
      nonstandard slist comtainer.  (Singly-linked version of
      STL std::list.)

    o Template query mechanism and user manual had several
      mismatches.  Made manual match actual behavior, or
      made library match documented behavior, as apropriate.
      Initial patch by Jürgen MF Gleiss, with corrections and
      enhancements by Warren Young.

    o Collapsed mysql_* date and time base classes' methods and
      data into the subclasses.  Also, DateTime no longer derives
      from Date and Time; you could get away with that in the
      old hierarchy, but now it creates an inheritance diamond,
      and allows unsupported concepts like comparing a Time to
      a DateTime.

    o Removed "field name" form of Row::field_list().  It was
      pretty much redundant -- if you have the field names, why
      do you need a list of field names?

    o ColData can convert itself to bool now.  Thanks for this
      patch go to Byrial Jensen.

    o Removed simp_list_b type; wasn't being used, and doesn't
      look to be useful for end-user code.

    o Several methods that used to take objects by value now
      do so by const reference, for efficiency.

    o Several variable and function renamings so that MySQL++
      isn't needlessly tied to MySQL.  Even if we never make
      the library work with other database servers, there's
      little point in tying this library to MySQL blindly.

    o Renamed all private data members of MySQL++ classes to
      have trailing underscores.

    o 'private' section follows 'public' section in all classes
      now.

    o Removed mysql++.hh and sqlplus.hh backwards-compatibility
      headers.

    o Added copy ctors to Date/Time classes so that they will
      work in SSQLS under GCC 4.0.0.  Without these, the compiler
      couldn't make the conversion from raw MySQL row data.

    o Fixed a bunch of GCC 4.0 pedantic warnings: added virtual
      dtors to all base classes, calling base class ctors from leaf
      classes, etc.

    o All warnings fixed under VC++ at warning level 3.  (Mostly
      harmless signedness and integer conversion stuff.)

    o Updated LGPL license/copyright comments at the top of
      several files to use FSF's new physical address.

    o Relicensed user manual under a close variant of the Linux
      Documentation Project License, as it's designed for
      documentation, which the LGPL is not.  Permission for this
      received from Kevin Atkinson and MySQL AB.

    o Added ABI and API breakages chapter to user manual.  It
      is basically a subset of this ChangeLog, with only the
      information an end-user must know when migrating between
      versions.

    o Reworked user manual's DocBook code quite a bit after
      reading Bob Stayton's book "DocBook XSL" 3/e.  Better handling
      of stylesheets, taking advantage of some superior DocBook
      features, prettier output (especially the HTML version), etc.

    o Rewrote doc/userman/README to make it clearer how to get
      started contributing to the user manual.  It's essentially a
      "getting started with DocBook" guide now!

    o Lots of small text improvements to user and reference
      manuals.  Aside from the obvious tracking of library changes,
      made a bunch of minor style and clarity improvements.

    o Added CSS stylesheets for userman and refman to
      make the HTML versions of each a) not ugly; and b) match
      tangentsoft.net.  (Yes, some may say that these are incompatible
      goals....)

    o Standardized exception handling code in the examples that
      use it.

    o Fixed a potential memory leak due to exceptions thrown from
      ResUse.  Thanks for this patch go to Chris Frey.

    o Using new "no exceptions" feature of library in simple1
      example, so it is now truly simple.

    o simple1 example no longer depends as much on util module, so
      that all of the important code is in one place.  Makes
      learning MySQL++ a little less intimidating.

    o Added new simple2 and usequery examples, to demonstrate
      the proper way to handle a "use" query, with exceptions
      disabled, and not, respectively.  Added them to the user
      manual, in the appropriate place.

    o Refactored the "print stock table" example functions
      again, to make code using them clearer.

    o UTF-8 to UCS-2 handling in examples is now automatic on
      Windows.

    o Removed debug code from Windows Unicode output examples
      that slipped into previous release.

    o resetdb example is now clearer, and more robust in the
      face of database errors.

    o Simplified connect_to_db() in examples' util module.

    o Added sample autoconf macro for finding MySQL++ libraries, for
      people to use in their own autotools-based projects.

    o Lots and lots of minor cleanups not worth mentioning
      individually...


1.7.40, 2005.05.26 (r719)

    o Multiple item form of insert() now works if you're using the
      SQLQuery class, or its derivative, Query.  Thanks to Mark
      Meredino for this patch.

    o Fixed a bug in const_string::compare(), in which MySQL++
      would walk off the end of the shorter of the two strings.
      All was well if the two were the same length.

    o ResUse::operator=() now fully updates the object, so it's more
      like the behavior of the full ctor.

    o All source files now contain a license and copyright statement
      somewhere within them.

    o Optimized mysql++.h a bit: it now #includes only the minimum set
      of files required, and there is now an idempotency guard.
      This improves compile times a smidge, but mainly it was
      done to clean up the generated #include file graph in the
      reference manual.  Before, it was a frightful tangle because
      we #included everything except custom*.h.

    o Constness fix in MySQL++ date/time classes to avoid compiler
      warnings with SSQLS.  Thanks to Wolfram Arnold for this patch.

    o Fixed some compiler warnings in custom*.h.  Thanks to Chris Frey
      for this patch.

    o Added "Submitting Patches" and "Maintaining a Private CVS
      Repository" sections to the HACKERS file.  Thanks to Chris
      Frey for the source material for these sections.  The HACKERS
      file was improved in several other ways at the same time.

    o PDF version of user manual no longer has links to the reference
      manual.  They were ugly, and they were broken anyway due to the
      way we move the PDFs after generating them.  If you want
      interlinked manuals, use the HTML version.

    o PDF version of user manual now has hard page breaks between
      chapters.

    o Removed complic1 example.  Wasn't pulling its own weight.
      Everything it is supposed to demonstrate is shown in other
      examples already.

    o Refactored print_stock_table() in examples/util module to be
      four functions, and made all the examples use various of
      these functions where appropriate.  Before, several of
      the examples had one-off stock table printing code because
      print_stock_table() wasn't exactly the right thing, for one
      reason or another.  One practical problem with this is that
      some of the examples missed out on the recent Unicode updates;
      now such a change affects all examples the same way.

    o Since so many of the examples rely on the util module, the user
      manual now covers it.  The simple1 example in the user manual
      didn't make much sense before, in particular, because it's
      really just a driver for the util module.

    o Added custom5 example.  It shows how to use the equal_list()
      functionality of SSQLS.  Thanks to Chris Frey for the original
      version of this program.  (I simplified it quite a bit after
      accepting it.)

    o New user manual now covers the value_list(), equal_list() and
      field_list() stuff that the old manual covered but which was
      left out in previous versions of the new manaul.  Most of the
      examples are the same, but the prose is almost completely new.
      This new section includes the custom5 example.

    o Every declaration in MySQL++ is now documented in the reference
      manual, or explicitly treated as "internal only".

    o Improved docs for MySQL++'s mechanism to map between MySQL
      server types and C++ types.  Initial doc patch by Chris Frey,
      which I greatly reworked.

    o Improved a lot of existing reference manual documentation while
      adding the new stuff.

    o Expanded greatly on the exception handling discussion in the user
      manual.

    o Added all-new "Quoting and Escaping" section to the user
      manual's Tutorial chapter.  Moved some existing comments on
      quoting and escaping around and added some new ones to other
      sections as a result.

    o Added all-new "Handling SQL Nulls" section to the user manual's
      Tutorial chapter.

    o Many improvements to the Overview section of the user manual.

    o Row::operator[] reference now explains the right and wrong way to
      use the values it returns.  This is in response to a mailing list
      post where someone was incorrectly using this feature and getting
      a bunch of dangling pointers.

    o Updated Doxyfile so 1.3.19.1 parses it without warnings.  Still
      works with versions back to 1.2.18, at least.  (These are
      the versions shipped with Fedora Core 3 and Red Hat Linux 9,
      respectively.)

    o Using a superior method to make Doxygen ignore certain sections
      of the source code.  Between this change and the fact that
      everything not so ignored is documented, Doxygen no longer
      generates any warnings.

    o Lots of code style updates.  Everything should now be consistently
      formatted.


1.7.35, 2005.05.05 (r601) The "Cinco de Mayo" release

    o Added a "how to use Unicode with MySQL++" chapter to the user
      manual.  (Too bad "Cinco de Mayo" doesn't have any accented
      characters.  That would be just _too_ precious.)

    o VC++ examples now use the Unicode Win32 APIs, so they can display
      Unicode data from MySQL++.

    o Added an optional conversion function to examples/util.cpp to
      handle the conversion from UTF-8 to UCS-2 on Win32.

    o Moved "brief history of MySQL++" from intro section of refman to
      intro section of userman.

    o Lots of small bits of documentation polishing.
    
    o Made some minor constness fixes.  Thanks to Erwin van Eijk
      for this patch.

    o Made some warning fixes for GCC 4.0.  Not all warnings are
      fixed, because some of the needed changes would break the ABI.
      Thanks to Chris Frey for this patch.

    o Added lib/Doxyfile to distribution.
    

1.7.34, 2005.04.30 (r573)

    o Added a multiple-insert method for Query, which lets you insert
      a range of records from an STL container (or the whole thing,
      if you like) in a single SQL query.  This is faster, and it
      reduces coding errors due to less repetition.  Thanks to Mark
      Meredino for the patch.

    o Reference and user manual now get rebuilt automatically when
      required.  (E.g. on 'make dist', or explicitly now through 'make
      docs'.)

    o Made it easier to change the maximum number of SSQLS data members
      in generated custom-macros.h file.  It used to be hard-coded in
      several places in lib/custom.pl; now it's a variable at the top of
      the file.

    o Changed default SSQLS data member limit to 25, which is what it
      has been documented as for a long time now.  It was actually 26
      within custom.pl.

    o Fixed a regression in previous version.

    o Trimmed some fat from the distribution packages.

    o Some more small doucmentation improvements.


1.7.33, 2005.04.29 (r555)

    o Worked around an overloaded operator lookup bug in VC++ 7.1
      that caused SSQLS insert, replace and update queries to get
      mangled.  (Symptom was that custom2 and custom3 examples didn't
      work right.)  Thanks to Mark Meredino for digging up the
      following, which explains the problem and gives the solution:

      http://groups-beta.google.com/group/microsoft.public.vc.stl/browse_thread/thread/9a68d84644e64f15

    o Some VC++ warning fixes.

    o Major documentation improvements:
    
        o Using DocBook for user manual and Doxygen for reference
          manual.  The former now references the latter where
          useful.

        o Split out HACKERS and CREDITS files from main README,
          and improved remaining bits of README.

        o Moved the text from the old v1.7.9 LaTeX-based
          documentation over into the new systems, and reworked
          it to more closely resemble English.

        o Added a lot of new material to documentation, and
          simplified a lot of what already existed.

        o Documentation is now being built in HTML and PDF forms.

    o ebuild file updated to take advantage of recent configure script
      features.  Thanks to Chris Frey for this patch.



1.7.32, 2005.03.10 (r479)

    o Example building may now be skipped with --disable-examples
      configure script flag.

    o Changed stock items added in resetdb.  One is now UTF-8 encoded,
      to show that basic use of Unicode with MySQL++ is easy, yet not
      foolproof.  (See formatting of table on systems where cout isn't
      UTF-8 aware!)  Other stock items now follow a theme, for your
      amusement.  :)

    o custom3 example now changes UTF-8 item's name to the 7-bit ASCII
      equivalent.  Previously, this example would fix a spelling error
      in the table.

    o resetdb example now says 'why' when it is unable to create the
      sample database.

    o Small formatting change to print_stock_table(), used by several
      examples.

    o Was issuing a VC++-specific warning-disable pragma when built by
      any Windows compiler.  Fixed.
    

1.7.31, 2005.03.05 (r462) The "Inevitable Point-one Followup" release

    o Check for threads support must now be explicitly requested via
      configure script's new --enable-thread-check flag.

    o Fix for contacting MySQL server on a nonstandard port number.
      Thanks to Chris Frey for this patch.

    o Example programs using standard command line format now accept a
      fourth optional parameter, a port number for the server.  Thanks
      to Chris Frey for this patch.

    o One more g++ 3.4 pedantic warning fix by Chris Frey.

    o Exception handling in resetdb is no longer nested, because you'd
      get a segfault on some systems when an exception was thrown from
      one of the inner try blocks.

    o Improvements to Connection class's handling of locking mechanism.
      Concept based on patches by Rongjun Mu.

    o Implemented the declared-but-never-defined Query::lock().  Thanks
      to Rongjun Mu for this patch.
    
    o Cleaned up some unclear if/else blocks in connection.cpp by
      adding explicit braces, correct indenting and putting normal
      code path in the if side instead of the else.


1.7.30, 2005.02.28 (r443) The "Power of Round Numbers" release

    o bootstrap script now accepts a 'pedantic' argument, which sets a
      bunch of CFLAGS that make g++ very picky about the code it
      accepts without warnings.
      
    o Fixed a bunch of things that generated warnings with g++ in
      pedantic mode. Only two warnings remain, having to do with
      floating point comparisons.  (See Wishlist for plans on how to
      deal with these.)  Thanks to Chris Frey for this patch.

    o Split long tests out of configure.in into M4 files in new config
      subdir.  This makes configure.in easier to read.

    o Added preliminary thread support.  Currently, this just means that
      we detect the required compiler and linker thread flags, and link
      against the proper thread-safe libraries.  THERE MAY BE
      UN-THREAD-SAFE CODE IN MYSQL++ STILL!

    o Standard C++ exceptions are the default now.  Old pre-Standard
      exception stuff removed.

    o Row::lookup_by_name() will throw the new BadFieldName exception if
      you pass a bad field name.  Thanks for this patch to Chris Frey.

    o Row::operator[] will throw a Standard C++ out of bounds exception
      by way of std::vector::at() if you pass it a bad index.  Thanks
      for this patch to Chris Frey.

    o Setting Connection::is_connected flag to false on close().
      Previously, is_connected() would continue to return true after
      close() was called.

    o All number-to-string conversion ctors in SQLString class now use
      ostringstream to do the conversion.  Previously, we used
      snprintf(), which isn't available on all systems.  Also, we used a
      C99 format specifier for the "long long" conversion, which is also
      not available on all systems.  This new ostringstream code should
      be platform-independent, finally.


1.7.28, 2005.02.04 (r403)

    o --with-mysql* flags to configure script now try the given
      directory explicitly, and only if that fails do they try
      variations, like tacking '/lib' and such onto it to try and find
      the MySQL includes and libraries.  Thanks to Matthew Walton for
      the patch.

    o Finally removed sql_quote.h's dependence on custom.h, by moving
      the one definition it needed from custom.h to deps.h.  This will
      help portability to compilers that can't handle the SSQLS macros,
      by making that part of the library truly optional.


1.7.27, 2005.01.12 (r395)

    o configure check for libmysqlclient now halts configuration if the
      library isn't found.  Previously, it would just be flagged as
      missing, and MySQL++ would fail to build.

    o Added sql_string.cpp to VC++ and BCBuilder project files.

    o Removed Totte Karlsson's 'populate' example, which never made it
      into the distribution anyway.

    o Removed last vestiges of 'dummy.cpp'.

    o Renamed *.cc to *.cpp in BCBuilder project files.

    o Worked around a BCBuilder C++ syntax processing bug in row.h.


1.7.26, 2004.12.17 (r382)

    o Moved all of the SQLString definitions out of the header and into
      a new .cpp file, reformatted it all, and made the integer
      conversion functions use snprintf() or _snprintf() instead of
      sprintf().  Also, widened some of the buffers for 64-bit systems.

    o Using quoted #include form for internal library headers, to avoid
      some problems with file name clashes.  (The headers should still
      be installed in their own separate directory for best results,
      however.)  Thanks to Chris Frey and Evan Wies for the patch and
      the discussion that lead to it.

    o Removed unnecessary semicolons on namespace block closures.
      Thanks to Evan Wies for this patch.

    o Fixed namespace handling in the legacy headers mysql++.hh and
      sqlplus.hh.  Thanks to Chris Frey for this patch.

    o #including iostream instead of ostream in lib/null.h for
      broader C++ compatibility.  (This may allow MySQL++ to work on GCC
      2.95.2 again, but this is unconfirmed.)

    o Detecting proper mysql_shutdown() argument handling automatically
      in platform.h for the Windows compiler case instead of making the
      user edit the file.  Thanks to Evan Wies for this patch.
    
    o Fixed examples/Makefile.simple to use new *.cpp file naming.

    o Fix to Gentoo ebuild file's exception configure switch handling.
      Thanks to Chris Frey for this patch.

    o Rebuilding lib/custom*.h intelligently now, to avoid unnecessary
      recompiles after running bootstrap script.


1.7.25, 2004.12.09 (r360)

    o Yet more fixes to the --with-mysql-lib and --with-mysql-include
      flags.

    o Added DLLEXPORT stuff to platform.h, hopefully so that someone
      can figure out how to make VC++ make a DLL version of MySQL++.

    o Renamed *.cc to *.cpp.

    o Made 'set -> myset' change in VC++ project files.

    o Some style changes (mostly whitespace) in header files.


1.7.24, 2004.12.08 (r343)

    o Fixed the --with-mysql-lib and --with-mysql-include flags'
      behavior, and extended their search ability to handle one other
      common case.  (Fixed by Steve Roberts)

    o Fixes to put freestanding functions in namespace mysqlpp.  (They
      weren't in the namespace, while all the class member functions
      were.)  This required bumping the ABI version number to 4.
      
    o Renamed set module to myset, to avoid conflicts with Standard C++
      Library's set.h when MySQL++ headers were installed into one of
      the standard system include directories.

    o Renamed all the idempotency guards to make them consistent in
      style and unique to MySQL++.

    o Reformatted all of lib/*.cc.


1.7.23, 2004.11.20 (r333)

    o Query::reset() now empties the stored query string.  If you
      subsequently stored a longer query in the object, you'd overwrite
      the previous query, but otherwise the longer part of the previous
      one would stick out past the new query.

    o We now look to the NO_LONG_LONGS macro only to decide whether to
      fake 64-bit integer support using 32-bit integers.

    o 64-bit integer support under Visual C++ may be working now, using
      that platform's __int64_t type.  This has not been tested.

    o Removed 64-bit integer support for Codewarrior on Mac OS 9 and
      earlier.  OS X uses GCC, so it requires no special support.

    o Added MinGW detection in platform.h.
    
    o If you pass a flag (-X) to the examples that take the standard
      parameters (resetdb, simple1, etc.), it prints a usage message.
    
    o Better error handling in resetdb example, where errors are the
      most critical.  (If that one runs without errors, the others
      probably will, too, and you have to run that one first.)

    o resetdb now reports success, rather than succeeding silently.

    o Removed the code in sample1 example that duplicated util module's
      print_stock_table(), and called that function instead.

    o Moved the preview() calls in the example programs to before the
      query execution calls, because execution modifies the query.

    o All examples that take the standard command line parameters now 
      exit when connect_to_db() fails in one of the ways that don't
      throw an exception, rather than bulling onward until the next
      MySQL database call fails because the connection isn't up.

    o dbinfo example now takes the standard command line parameters.

    o Much better output formatting in dbinfo example.

    o Calling reset() where appropriate in the various example programs.
      Before, the programs may have worked, but not for the right
      reason.  This lead some people to believe that calling reset()
      was not necessary.

    o Fixed an incorrect use of row["string"] in complic1 example.

    o Lots of code style improvements to the examples.

    o Some VC++ type warnings squished.  Some remain.
    

1.7.22, 2004.11.17 (r302)

    o Applied patches by Zahroof Mohammed to allow it to build under GCC
      3.4.2.  Tested on MinGW and Fedora Core 3 systems.

    o Removed all the forward declarations in defs.h, and added
      forward declarations where necessary in individual header files.
      #including defs.h in fewer locations as a result.

    o Legacy headers sqlplus.hh and mysql++.hh now declare they are
      using namespace mysqlpp, to allow old code to compile against the
      new library without changes.

    o Removed query_reset parameter from several class Query member
      functions.  In the implementation, these parameters were always
      overridden!  No sense pretending that we pay attention to these
      parameters.  This changes the ABI version to 3.

    o #including custom.h in sql_query.h again...it's necessary on GCC
      3.4.
    
    o bootstrap script runs lib/config.pl after configure.  This is
      just a nicety for those running in 'maintainer mode'.


1.7.21, 2004.11.05 (r273)

    o Generating a main mysql++ RPM containing just the library files
      and basic documentation, and the -devel package containing
      everything else.

    o Devel package contains examples now, along with a new Makefile
      that uses the system include and library files, rather than the
      automake-based Makefile.am we currently have which uses the files
      in the mysql++ source directory.

    o Renamed sqlplusint subdirectory in the package to lib.

    o Removed the obsolete lib/README file.

    o lib/sql_query.h no longer #includes custom.h, simplifying
      build-time dependencies and shortening compile times.


1.7.20, 2004.11.03 (r258)

    o Collapsed all numbered *.hh headers into a single *.h file.  For
      example, the contents of row1.hh, row2.hh and row3.hh are now in
      row.h.

    o While doing the previous change, broke several circular
      dependencies.  (The numbered file scheme was probably partly done
      to avoid this problem.)  The practical upshot of most of these
      changes is that some functions are no longer inline.

    o Removed define_short.hh and everything associated with it.  The
      library now uses the short names exclusively (e.g. Row instead of
      MysqlRow).

    o Put all definitions into namespace mysqlpp.  For most programs,
      simply adding a 'using namespace mysqlpp' near the top of the
      program will suffice to convert to this version.

    o Once again, the main include file was renamed, this time to
      mysql++.h.  Hopefully this is the last renaming!

    o mysql++.hh still exists.  It emits a compiler warning that the
      file is obsolete, then it #includes mysql++.h for you.

    o sqlplus.hh is back, being a copy of the new mysql++.hh.  Both of
      these files may go away at any time.  They exist simply to help
      people transition to the new file naming scheme.

    o Renamed mysql++-windows.hh to platform.h, and added code to it to
      handle #inclusion of config.h on autotools-based systems
      intelligently.  This fixes the config.h error when building under
      Visual C++.

    o There is now only one place where conditional inclusion of
      winsock.h happens: platform.h.

    o Beautified the example programs.


1.7.19, 2004.10.25 (r186)

    o Fixed an infinite loop in the query mechanism resulting from the
      strstream change in the previous version.  There is an overloaded
      set of str() member functions that weren't a problem when query
      objects were based on strstream.
     
    o Query mechanism had a bunch of const-incorrectness: there were
      several function parameters and functions that were const for
      the convenience of other parts of the code, but within these
      functions the constness was const_cast away!  This was evil
      and wrong; now there are fewer const promises, and only one is
      still quietly broken within the code.  (It's in the SQLQuery
      copy ctor implementation; it should be harmless.)

    o Removed operator=() in Query and SQLQuery classes.  It cannot take
      a const argument for the same reason we have to cast away const
      in the SQLQuery copy ctor.  It's tolerable to do this in the copy
      ctor, but intolerable in an operator.  Since the copy ctor is good
      enough for all code within the library and within my own code, I'm
      removing the operator.

    o Above changes required bumping the ABI to version 2.

    o Visual C++ projects now look for MySQL build files in c:\mysql,
      since that's the default install location.  (Previously, it was
      c:\program files\mysql.)


1.7.18, 2004.10.01 (r177)

    o Changed all the strstream (and friends) stuff to stringstream type
      classes.  Let there be much rejoicing.

    o Query object now lets you use store() even when the SQL query
      cannot return a result, such as a DROP TABLE command.  This is
      useful for sending arbitrary SQL to the server.  Thanks to
      Jose Mortensen for the patch.

    o Quote fix in configure.in, thanks to David Sward.

    o Renamed undef_short file to undef_short.hh.

    o Gentoo ebuild file is actually being shipped with the tarball,
      instead of just sitting in my private CVS tree since 1.7.14 was
      current.  Ooops....


1.7.17, 2004.09.16 (r170)

    o Reverted one of the VC++ warning fix changes from 1.7.16 that
      caused crashes on Linux.

    o Added a configure test that conditionally adds the extra 'level'
      parameter to mysql_shutdown() that was added in MySQL 4.1.3 and
      5.0.1.


1.7.16, 2004.09.13 (r160)

    o Building VC++ version with DLL version of C runtime libraries, and
      at warning level 3 with no warnings emitted.

    o VC++ build no longer attempts to fake "long long" support.  See
      the Wishlist for further thoughts on this.


1.7.15, 2004.09.02 (r144)

    o Renamed Configure file to common.am, to avoid file name conflict
      with configure script on case-sensitive file systems.

    o Added ebuild file and ebuild target to top-level Makefile for
      Gentoo systems.  Thanks to Chris Frey for this.

    o Small efficiency improvements to BadQuery exception handling.
      Initial idea by Chris Frey, improvements by Warren Young.


1.7.14, 2004.08.26 (r130)

    o Builds with Visual C++ 7.1.

    o Fixed a bug in custom macro generation that caused problems with
      GCC 3.4.  (X_cus_value_list ctor definition was broken.)


1.7.13, 2004.08.23 (r92)

    o Removed USL CC support.  (System V stock system compiler.)  Use
      GCC on these platforms instead.

    o Added examples/README, explaining how to use the examples, and
      what they all do.

    o Most of the example programs now accept command line arguments for
      host name, user name and password, like resetdb does.

    o Renamed sinisa_ex example to dbinfo.

    o Several Standard C++ syntax fixes to quash errors emitted by
      GCC 3.4 and Borland C++ Builder 6.  Thanks to Steffen Schumacher
      and Totte Karlsson for their testing and help with these.

    o Added proper #includes for BCBuilder, plus project files for same.
      Thanks to Totte Karlsson for these.


1.7.12, 2004.08.19 (r63)

    o Many Standard C++ fixes, most from the GCC 3.4 patch by
      Rune Kleveland.

    o Added Wishlist file to distribution.

    o Fixed a problem in the bootstrap script that caused complaints
      from the autotools on some systems.

    o RPM building is working properly now.

    o Fixed the idempotency guard in datetime1.hh.


1.7.11, 2004.08.17 (r50)

    o Renamed mysql++, defs and define_short files, adding .hh to the
      end of each.  (They're header files!)  This shouldn't impact
      library users, since these are hopefully used internal to the
      library only.

    o Removed sqlplus.hh file.  Use mysql++.hh instead.
    
    o Added mysql++.spec, extracted from contributed 1.7.9 source RPM, 
      and updated it significantly.  Also, added an 'rpm' target to
      Makefile.am to automate the process of building RPMs.

    o Added bootstrap and LGPL files to distribution tarball.

    o Added pre-1.7.10 history to this file.

    o Removed .version file.  Apparently it's something required by old
      versions of libtool.


1.7.10, 2004.08.16 (r27)

    o Maintenance taken over by Warren Young (mysqlpp at etr dash usa
      dot com.) See http://lists.mysql.com/plusplus/3326 for details.

    o Applied many of the GCC 3.x patches submitted for 1.7.9 over
      the years.  This allows it to build on everything from 3.0 to
      3.3.3, at least.  Because so many patches are rolled up in one
      big jump, it's difficult to describe all the changes and where
      they came from.  Mostly they're Standard C++ fixes, as GCC
      has become more strict in the source code that it will accept.

    o MysqlRow used to overload operator[] for string types as well as
      integers so you could look up a field by its name, rather than by
      its index.  GCC 3.3 says this is illegal C++ due to ambiguities in
      resolving which overload should be used in various situations.
      operator[] is now overloaded only for one integer type, and a
      new member function lookup_by_name() was added to maintain the old
      by-field-name functionality.

    o Fixed another operator overloading problem in SSQLS macro
      generation with GCC 3.3.

    o The _table member of SSQLS-defined structures is now const char*,
      so you can assign to it from a const char* string.

    o Got autoconf/automake build system working with current versions
      of those tools again.  Removed the generated autotools files from
      CVS.

    o Renamed library file from libsqlplus to libmysqlpp.


1.7.9 (May 1 2001) Sinisa Milivojevic <sinisa@mysql.com>

    * Fixed a serious bug in Connection constructor when reading MySQL
    * options
    * Improved copy constructor and some other methods in Result /
    * ResUse
    * Many other minor improvements
    * Produced a complete manual with chapter 5 included
    * Updated documentation, including a Postscript format

1.7.8 (November 14 2000) Sinisa Milivojevic <sinisa@mysql.com>

    * Introduced a new, standard way of dealing with C++ exceptions.
    * MySQL++ now supports two different methods of tracing exceptions.
    * One is by the fixed type (the old one) and one is standard C++
    * type by the usage of what() method. A choice of methods has to be
    * done in building a library. If configure script is run with
    * -enable-exception option , then new method will be used. If no
    * option is provided, or -disable-exception is used, old MySQL++
    * exceptions will be enforced. This innovation is a contribution of
    * Mr. Ben Johnson <ben@blarg.net>
    * MySQL++ now automatically reads at connection all standard MySQL
    * configuration files
    * Fixed a bug in sql_query::parse to enable it to parse more then 99
    * char's
    * Added an optional client flag in connect, which will enable usage
    * of this option, e.g. for getting matched and not just affected
    * rows. This change does not require any changes in existing
    * programs
    * Fixed some smaller bugs
    * Added better handling of NULL's. Programmers will get a NULL
    * string in result set and should use is_null() method in ColData to
    * check if value is NULL
    * Further improved configuration
    * Updated documentation, including a Postscript format

1.7.6 (September 22 2000) Sinisa Milivojevic <sinisa@mysql.com>

    * This release contains some C++ coherency improvements and scripts
    * enhacements
    * result_id() is made available to programmers to fetch
    * LAST_INSERT_ID() value
    * Connection constroctur ambiguity resolved, thanks to marc@mit.edu
    * Improved cnnfigure for better finding out MySQL libraries and
    * includes
    * Updated documentation, including a Postscript format

1.7.5 (July 30 2000) Sinisa Milivojevic <sinisa@mysql.com>

    * This release has mainl bug fixes  and code improvements
    * A bug in FieldNames::init has been fixed, enabling a bug free
    * usage of this class with in what ever a mixture of cases that is
    * required
    * Changed behaviour of ResUse, Result and Row classes, so that they
    * could be re-used as much as necessary, without any memory leaks,
    * nor with any re-initializations necessary
    * Fixed all potential leaks that could have been caused by usage of
    * delete instead of delete[] after memory has been allocated with
    * new[]
    * Deleted all unused classes and macros. This led to a reduction of
    * library size to one half of the original size. This has
    * furthermore brought improvements in compilation speed
    * Moved all string manipulation from system libraries to
    * libmysqlclient, thus enabling uniformity of code and usage of 64
    * bit integers on all platforms, including Windows, without
    * reverting to conditional compilation. This changes now requires
    * usage of mysql 3.23 client libraries, as mandatory
    * Changed examples to reflect above changes
    * Configuration scripts have been largely changed and further
    * changes shall appear in consecutive sub-releases. This changes
    * have been done and shall be done by our MySQL developer Thimble
    * Smith <tim@mysql.com>
    * Changed README, TODO and text version of manual. Other versions of
    * manual have not been updated
    * Fixed .version ``bug''. This is only partially fixed and version
    * remains 1.7.0 due to some problems in current versions of libtool.
    * This shall be finally fixed in a near future
    * Several smaller fixes and improvements
    * Added build.sh script to point to the correct procedure of
    * building of this library. Edit it to add configure options of your
    * choice

1.7 (May17 2000) Sinisa Milivojevic <sinisa@mysql.com>

    * This is mainly a release dealing with bug fixes, consistency
    * improvements and easier configure on some platforms
    * A bug in fetch_row() method of ResUse class has been fixed. Beside
    * changes that existed in a distributed patch, some additional error
    * checking has been introduced
    * A bug in escape manipulator has been fixed that could cause an
    * error if all characters had to be escaped
    * An inconsistency in column indexing has been fixed. Before this
    * version, column names in row indexing with strings, i.e.
    * row[<string>] , has been case sensitive, which was inconsistent
    * with MySQL server handling of column names
    * An inconsistency in conversion from strings to integers or floats
    * has been fixed. In prior version a space found in data would cause
    * a BadConversion exception. This has been fixed, but 100%
    * consistency with MySQL server has not been targeted, so that other
    * non-numeric characters in data will still cause BadConversion
    * exception or error. As this API is used in applications, users
    * should provide feedback if full compatibility with MySQL server is
    * desired, in which case BadConversion exception or error would be
    * abolished in some of future versions
    * A new method in ColData class has been introduced. is_null()
    * method returns a boolean to denote if a column in a row is NULL.
    * Finally, as of this release, testing for NULL values is possible.
    * Those are columns with empty strings for which is_null() returns
    * true.
    * Some SPARC Solaris installations had C++ exception problems with
    * g++ 2.95.2 This was a bug that was fixed in GNU gcc, as from
    * release 2.95 19990728. This version was thoroughly tested and is
    * fully functional on SPARC Solaris 2.6 with the above version of
    * gcc.
    * A 'virtual destructor ' warning for Result class has been fixed
    * Several new functions for STL strings have been added. Those
    * functions (see string_util.hh) add some of the functionality
    * missing in existing STL libraries
    * Conversion for 64 bit integers on FreeBSD systems has been added.
    * On those systems _FIX_FOR_BSD_ should be defined in CXXFLAGS prior
    * to configuring. Complete conversion to the usage of functions for
    * integer conversion found in mysqlclient library is planned for one
    * of the next releases
    * A completely new, fully dynamic, dramatic and fully mutable result
    * set has been designed and will be implemented in some of 2.x
    * releases
    * Several smaller fixes and improvements, including defaulting
    * exceptions to true, instead of false, as of this version
    * An up-to-date and complete Postscript version of documentation is
    * included in this distribution
    * Large chunks of this manual are changed, as well as README and
    * TODO files.

1.6 (Feb 3 2000) Sinisa Milivojevic <sinisa@mysql.com>

    * This is a major release as it includes new features and major
    * rewrites
    * Automatic quoting and escaping with streams. It works
    * automatically , depending on the column type. It will work with <<
    * on all ostream derived types. it is paricularly handy with query
    * objects and strstreams. Automatic quoting and escaping on cout,
    * cerr and clog stream objects is intentionally left out, as quoting
    * / escaping on those stream objects is not necessary. This feature
    * can be turned of by setting global boolean dont_quote_auto to
    * true.
    * Made some major changes in code, so that now execute method should
    * be used only with SSQL and template queries, while for all other
    * query execution of UPDATE's, INSERT's, DELETE's, new method exec()
    * should be used. It is also faster.
    * New method get_string is inroduced for easier handling / casting
    * ColData into C++ strings.
    * Major rewrite of entire code, which led to it's reduction and
    * speed improvement. This also led to removal of several source
    * files.
    * Handling of binary data is introduced. No application program
    * changes are required. One of new example programs demonstrates
    * handling of binary data
    * Three new example programs have been written and thoroughly
    * tested. Their intention is to solve some problems addressed by
    * MySQL users.
    * Thorough changes is Makefile system has been made
    * Better configuration scripts are written, thanks to D.Hawkins
    * <dhawkins@cdrgts.com>
    * Added several bug fixes
    * Changed Manual and Changelog

1.5 (Dec 1 1999) Sinisa Milivojevic <sinisa@mysql.com>

    * Fixed bug in template queries, introduced in 1.4 (!)
    * Fixed connect bug
    * Fixed several bug in type_info classes
    * Added additional robustness in classes
    * Added additional methods for SQL type info
    * Changed Changelog and README

1.4 (Nov 25 1999) Sinisa Milivojevic <sinisa@mysql.com>

    * Fixed bug in store and storein methods
    * Fixed one serious memory leak
    * Fixed a very serious bug generated by gcc 2.95.xx !!
    * Added robustness in classes, so that e.g. same query and row
    * objects can be re-used
    * Changed sinisa_ex example to reflect and demonstrate this
    * stability
    * Changed Changelog and README
    * Few other bug fixes and small improvements and speed-ups

1.3 (Nov 10 1999) Sinisa Milivojevic <sinisa@mysql.com>

    * Fixed several erronous definitions
    * Further changed source to be 2.95.2 compatible
    * Expunged unused statements, especially dubious ones, like use of
    * pointer_tracker
    * Corrected bug in example file fieldinf1
    * Finally fixed mysql_init in Connection constructor, which provided
    * much greater stability !
    * Added read and get options, so that clients, like mysqlgui can use
    * it
    * Changed Changelog and README
    * Many other bug fixes.

1.2 (Oct 15 1999) Sinisa Milivojevic <sinisa@mysql.com>

    * First offical release. Version 1.0 and 1.1 were releases by Sinisa
    * before I (Kevin Atkinson) made him the offical maintainer,
    * Many manual fixes.
    * Changed README and Changelog
    * Changed source to be compilable by gcc 2.95.xx, tribute to Kevin
    * Atkinson <kevinatk@home.com>
    * Added methods in Connection class which are necessary for
    * fullfilling administrative functions with MySQL
    * Added many bug fixes in code pertaining to missing class
    * initializers , as notified by Michael Rendell <michael@cs.mun.ca>
    * Sinisa Milivojevic <sinisa@mysql.com> is now the offical
    * maintainer.

1.1 (Aug 2 1999) Sinisa Milivojevic <sinisa@mysql.com>

    * Added several bug fixes
    * Fixed memory leak problems and variables overlapping problems.
    * Added automake and autoconf support by loic@ceic.com
    * Added Makefile for manual
    * Added support for cygwin
    * Added example sinisa_ex (let modesty prevail) which used to crash
    * a lot when memory allocation, memory leak and overlap problems
    * were present. Smooth running of this example proves that all those
    * bugs are fixed
    * Corrected bugs in sql_query.cc regarding delete versus delete[]
    * and string length in manip.cc
    * Changed manual
    * Changed README
    * Many other smaller things

1.0 (June 9 1999) Michael Widenius <monty@monty.pp.sci.fi>

    * Added patches from Orion Poplawski <orion@bvt.com> to support the
    * UnixWare 7.0 compiler

.64.1.1a (Sep 27 1998)

    * Fixed several bugs that caused my library to fail to compile with
    * egcs 1.1. Hopefully it will still compile with egcs 1.0 however I
    * have not been able to test it with egcs 1.0.
    * Removed some problem causing debug output in sql++pretty.

.64.1a (Aug 1 1998)

    * Added an (almost) full guide to using Template Queries.
    * Fixed it so the SQLQuery will throw an exception when all the
    * template parameters are not provided.
    * Proofread and speedchecked the manual (it really needed it).
    * Other minor document fixes.

.64.0.1a (July 31 1998)

    * Reworked the Class Reference section a bit.
    * Minor document fixes
    * Added more examples for SSQLS.
    * Changed the syntax of equal_list for SSQLS from equal_list (cchar
    * *, Manip, cchar *) to (cchar *, cchar *, Manip).
    * Added set methods to SSQLS. These new methods do the same thing as
    * there corresponding constructors.
    * Added methods for creating a mysql_type_info from a C++ type_info.

.64.a (July 24 1998)

    * Changed the names of all the classes so they no longer have to
    * have Mysql in the begging of it. However if this creates a problem
    * you can define a macro to only use the old names instead.
    * The Specialized SQL Structures (formally known as Custom Mysql
    * Structures) changed from mysql_ to sql_.
    * Added the option of using exceptions thoughout the API.
    * ColData (formally known as MysqlStrings) will now throw an
    * exception if there is a problem in the conversion.
    * Added a null adapter.
    * Added Mutable Result Sets
    * Added a very basic runtime type identification for SQL types
    * Changed the document format from POD to LYX .
    * Am now using a modified version of Perceps to extract the class
    * information directly from the code to make my life easier.
    * Added an option of defining a macro to avoid using the automatic
    * conversion with binary operators.
    * Other small fixed I probully forgot to mentune.

.63.1.a

    * Added Custom Mysql Structures.
    * Fixed the Copy constructor of class Mysql
    * Started adding code so that class Mysql lets it children now when
    * it is leaving
    * Attempted to compile it into a library but still need help. As
    * default it will compile as a regular program.
    * Other small fixes.

.62.a (May 3 1998)

    * Added Template Queries
    * Created s separate SQLQuery object that is independent of an SQL
    * connection.
    * You no longer have to import the data for the test program as the
    * program creates the database and tables it needs.
    * Many small bug fixes.

.61.1.a (April 28 1998)

    * Cleaned up the example code in test.cc and included it in the
    * manual.
    * Added an interface layout plan to the manual.
    * Added a reverse iterator.
    * Fixed a bug with row.hh (It wasn't being included because of a
    * typo).

.61.0.a

    * Major interface changes. I warned you that the interface may
    * change while it is in pre-alpha state and I wasn't kidding.
    * Created a new and Separate Query Object. You can no longer execute
    * queries from the Mysql object instead you have to create a query
    * object with Mysql::query() and use it to execute queries.
    * Added the comparison operators to MysqlDate, MysqlTime and
    * MysqlDateTime. Fixed a few bugs in the MysqlDate... that effected
    * the stream output and the conversion of them to strings.
    * Reflected the MysqlDate... changes in the manual.
    * Added a new MysqlSet object and a bunch of functions for working
    * with mysql set strings.

.60.3a (April 24 1998)

    * Changed strtoq and strtouq to strtoll and strtull for metter
    * compatibility Minor Manual fix.
    * Changed makefile to make it more compatible with Solaris (Thanks
    * Chris H)
    * Fixed bug in comparison functions so that they would compare in he
    * right direction.
    * Added some items to the to do list be sure to have a look.

Changes to examples/store_if.cpp.

1
2
3
4
5
6

7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
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
56
57










58





59


60







61




62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
/***********************************************************************
 store_if.cpp - Demonstrates Query::store_if(), showing only the rows
	from the sample table with prime quantities.  This isn't intended
	to be useful, only to show how you can do result set filtering that
	outstrips the power of SQL.


 Copyright (c) 2005-2010 by Educational Technology Resources, Inc.
 Others may also hold copyrights on code in this file.  See the CREDITS
 file in the top directory of the distribution for details.

 This file is part of MySQL++.

 MySQL++ is free software; you can redistribute it and/or modify it
 under the terms of the GNU Lesser General Public License as published
 by the Free Software Foundation; either version 2.1 of the License, or
 (at your option) any later version.

 MySQL++ is distributed in the hope that it will be useful, but WITHOUT
 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
 License for more details.

 You should have received a copy of the GNU Lesser General Public
 License along with MySQL++; if not, write to the Free Software
 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
 USA
***********************************************************************/


#include "cmdline.h"
#include "printdata.h"
#include "stock.h"

#include <mysql++.h>





#include <iostream>








#include <math.h>



















// Define a functor for testing primality.
struct is_prime
{
	bool operator()(const stock& s)
	{
		if ((s.num == 2) || (s.num == 3)) {
			return true;	// 2 and 3 are trivial cases
		}
		else if ((s.num < 2) || ((s.num % 2) == 0)) {
			return false;	// can't be prime if < 2 or even
		}
		else {
			// The only possibility left is that it's divisible by an
			// odd number that's less than or equal to its square root.
			for (int i = 3; i <= sqrt(double(s.num)); i += 2) {

				if ((s.num % i) == 0) {
					return false;
				}










			}





			return true;


		}







	}




};


int
main(int argc, char *argv[])
{
	// Get database access parameters from command line
	mysqlpp::examples::CommandLine cmdline(argc, argv);
	if (!cmdline) {
		return 1;
	}

	try {
		// Establish the connection to the database server.
		mysqlpp::Connection con(mysqlpp::examples::db_name,
				cmdline.server(), cmdline.user(), cmdline.pass());

		// Collect the stock items with prime quantities
		std::vector<stock> results;
		mysqlpp::Query query = con.query();
		query.store_if(results, stock(), is_prime());

		// Show the results
		print_stock_header(results.size());
		std::vector<stock>::const_iterator it;
		for (it = results.begin(); it != results.end(); ++it) {
			print_stock_row(it->item.c_str(), it->num, it->weight,
					it->price, it->sDate);
		}
	}
	catch (const mysqlpp::BadQuery& e) {
		// Something went wrong with the SQL query.
		std::cerr << "Query failed: " << e.what() << std::endl;
		return 1;
	}
	catch (const mysqlpp::Exception& er) {
		// Catch-all for any other MySQL++ exceptions
		std::cerr << "Error: " << er.what() << std::endl;
		return 1;
	}

	return 0;
}
|
<
<
<
|

>
|
|
|



















>
|
|
|

|

>
>
>
>
|
>
|
>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
|
>
>
>
>
>
>
>
|
<
|
|
<
<
<
<
|
<
<
|
<
<
<
<
>
|
<
|
>
>
>
>
>
>
>
>
>
>
|
>
>
>
>
>
|
>
>
|
>
>
>
>
>
>
>
|
>
>
>
>



<
<
<
<
<
<
<
<
|
<
<
<
<

<
<
<
<
|
<
<
<
<
<
<
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
1



2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
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
56
57
58
59
60
61
62
63
64
65
66

67
68




69


70




71
72

73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108








109




110




111






112














/// \file wnp_connection.h



/// \brief Declares the WindowsNamedPipeConnection class.

/***********************************************************************
 Copyright (c) 2007-2008 by Educational Technology Resources, Inc.
 Others may also hold copyrights on code in this file.  See the
 CREDITS.txt file in the top directory of the distribution for details.

 This file is part of MySQL++.

 MySQL++ is free software; you can redistribute it and/or modify it
 under the terms of the GNU Lesser General Public License as published
 by the Free Software Foundation; either version 2.1 of the License, or
 (at your option) any later version.

 MySQL++ is distributed in the hope that it will be useful, but WITHOUT
 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
 License for more details.

 You should have received a copy of the GNU Lesser General Public
 License along with MySQL++; if not, write to the Free Software
 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
 USA
***********************************************************************/

#if !defined(MYSQLPP_WNP_CONNECTION_H)
#define MYSQLPP_WNP_CONNECTION_H

#include "connection.h"

namespace mysqlpp {

/// \brief Specialization of \c Connection for Windows named pipes
///
/// This class just simplifies the connection creation interface of
/// \c Connection.  It does not add new functionality.

class MYSQLPP_EXPORT WindowsNamedPipeConnection : public Connection
{
public:
	/// \brief Create object without connecting it to the MySQL server.
	WindowsNamedPipeConnection() :
	Connection()
	{
	}

	/// \brief Create object and connect to database server over Windows
	/// named pipes in one step.
	///
	/// \param db name of database to use
	/// \param user user name to log in under, or 0 to use the user
	///		name the program is running under
	/// \param password password to use when logging in
	WindowsNamedPipeConnection(const char* db, const char* user = 0,
			const char* password = 0) :
	Connection()
	{
		connect(db, user, password);
	}

	/// \brief Establish a new connection using the same parameters as
	/// an existing connection.
	///
	/// \param other pre-existing connection to clone
	WindowsNamedPipeConnection(const WindowsNamedPipeConnection& other) :

	Connection(other)
	{




	}







	/// \brief Destroy object
	~WindowsNamedPipeConnection() { }


	/// \brief Connect to database after object is created.
	///
	/// It's better to use the connect-on-create constructor if you can.
	/// See its documentation for the meaning of these parameters.
	///
	/// If you call this method on an object that is already connected
	/// to a database server, the previous connection is dropped and a
	/// new connection is established.
	bool connect(const char* db = 0, const char* user = 0,
			const char* password = 0);

	/// \brief Check that given string denotes a Windows named pipe
	/// connection to MySQL
	///
	/// \param server the server address
	///
	/// \return false if server address does not denote a Windows
	/// named pipe connection, or we are not running on Windows
	static bool is_wnp(const char* server);

private:
	/// \brief Provide uncallable versions of the parent class ctors we
	/// don't want to provide so we don't get warnings about hidden
	/// overloads with some compilers
	WindowsNamedPipeConnection(bool) { }
	WindowsNamedPipeConnection(const char*, const char*, const char*,
			const char*, unsigned int) { }

	/// \brief Explicitly override parent class version so we don't get
	/// complaints about hidden overloads with some compilers
	bool connect(const char*, const char*, const char*, const char*,
			unsigned int) { return false; }
};










} // end namespace mysqlpp









#endif // !defined(MYSQLPP_WNP_CONNECTION_H)





















Changes to examples/threads.h.




1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
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


56
















































































































































































57




































































































58





59

60








































































































61
62












































































































































































63




/***********************************************************************
 threads.h - Abstracts away the differences between POSIX threads and
	Windows native threads.  Used by the cpool example only; we could
	keep this code inline there, but it's really just unimportant
	details.

 Copyright (c) 2008 by Educational Technology Resources, Inc.
 Others may also hold copyrights on code in this file.  See the
 CREDITS.txt file in the top directory of the distribution for details.

 This file is part of MySQL++.

 MySQL++ is free software; you can redistribute it and/or modify it
 under the terms of the GNU Lesser General Public License as published
 by the Free Software Foundation; either version 2.1 of the License, or
 (at your option) any later version.

 MySQL++ is distributed in the hope that it will be useful, but WITHOUT
 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
 License for more details.

 You should have received a copy of the GNU Lesser General Public
 License along with MySQL++; if not, write to the Free Software
 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
 USA
***********************************************************************/

#if !defined(MYSQLPP_THREADS_H)
#define MYSQLPP_THREADS_H

#include <mysql++.h>

#if defined(MYSQLPP_PLATFORM_WINDOWS)
#	define HAVE_THREADS
#	define CALLBACK_SPECIFIER WINAPI
	typedef DWORD thread_return_t;
	typedef LPVOID thread_arg_t;
	static int create_thread(LPTHREAD_START_ROUTINE worker, thread_arg_t arg)
	{
		return CreateThread(0, 0, worker, arg, 0, 0) ? 0 : GetLastError();





	}
	static void sleep(int s) { Sleep(s * 1000); }


#else

#	include "../config.h"


#	if defined(HAVE_UNISTD_H)

#		include <unistd.h>



#	endif






















































































































































































































#	if defined(HAVE_PTHREAD)


#		define HAVE_THREADS















#		define CALLBACK_SPECIFIER





		typedef void* thread_return_t;




































































































































































































		typedef void* thread_arg_t;










		static int create_thread(thread_return_t(*worker)(thread_arg_t),




















				thread_arg_t arg)


		{
















































































































































































			pthread_t pt;




































































































			return pthread_create(&pt, 0, worker, arg);





		}

#	endif








































































































#endif













































































































































































#endif // !defined(MYSQLPP_THREADS_H)

>
>
>

<
<
<
<
|
|
|
|



















|
|

|

|
|
|
|
|
|
|
|
>
>
>
>
>
|
<
>
>

>
|
>
>
|
>
|
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
>
>
>
>

>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>


>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
1
2
3
4




5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
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
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
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
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
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
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
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
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
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
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
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
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
/// \file query.h
/// \brief Defines a class for building and executing SQL queries.

/***********************************************************************




 Copyright (c) 1998 by Kevin Atkinson, (c) 1999-2001 by MySQL AB, and
 (c) 2004-2008 by Educational Technology Resources, Inc.  Others may
 also hold copyrights on code in this file.  See the CREDITS.txt file
 in the top directory of the distribution for details.

 This file is part of MySQL++.

 MySQL++ is free software; you can redistribute it and/or modify it
 under the terms of the GNU Lesser General Public License as published
 by the Free Software Foundation; either version 2.1 of the License, or
 (at your option) any later version.

 MySQL++ is distributed in the hope that it will be useful, but WITHOUT
 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
 License for more details.

 You should have received a copy of the GNU Lesser General Public
 License along with MySQL++; if not, write to the Free Software
 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
 USA
***********************************************************************/

#if !defined(MYSQLPP_QUERY_H)
#define MYSQLPP_QUERY_H

#include "common.h"

#include "noexceptions.h"
#include "qparms.h"
#include "querydef.h"
#include "result.h"
#include "row.h"
#include "stadapter.h"

#include <deque>
#include <iomanip>
#include <list>
#include <map>
#include <set>
#include <vector>


#ifdef HAVE_EXT_SLIST
#  include <ext/slist>
#else
#  if defined(HAVE_STD_SLIST) || defined(HAVE_GLOBAL_SLIST)
#      include <slist>
#  endif
#endif

namespace mysqlpp {

#if !defined(DOXYGEN_IGNORE)
// Make Doxygen ignore this
class MYSQLPP_EXPORT Connection;
#endif

/// \brief A class for building and executing SQL queries.
///
/// One does not generally create Query objects directly. Instead, call
/// mysqlpp::Connection::query() to get one tied to that connection.
///
/// There are several ways to build and execute SQL queries with this
/// class.
///
/// The way most like other database libraries is to pass a SQL
/// statement in either the form of a C or C++ string to one of the
/// \link mysqlpp::Query::execute() exec*(), \endlink
/// \link mysqlpp::Query::store() store*(), \endlink or use() methods.
/// The query is executed immediately, and any results returned.
///
/// For more complicated queries, it's often more convenient to build up
/// the query string over several C++ statements using Query's stream
/// interface. It works like any other C++ stream (\c std::cout,
/// \c std::ostringstream, etc.) in that you can just insert things
/// into the stream, building the query up piece by piece. When the
/// query string is complete, you  call the overloaded version of
/// \link mysqlpp::Query::execute() exec*(), \endlink
/// \link mysqlpp::Query::store() store*(), \endlink or
/// \link mysqlpp::Query::use() use() \endlink takes no parameters,
/// which executes the built query and returns any results.
///
/// If you are using the library's Specialized SQL Structures feature,
/// Query has several special functions for generating common SQL
/// queries from those structures. For instance, it offers the
/// \link mysqlpp::Query::insert() insert() \endlink method, which
/// builds an INSERT query to add the contents of the SSQLS to the
/// database. As with the stream interface, these methods only build
/// the query string; call one of the parameterless methods mentioned
/// previously to actually execute the query.
///
/// Finally, you can build "template queries". This is something like
/// C's \c printf() function, in that you insert a specially-formatted
/// query string into the object which contains placeholders for data.
/// You call the parse() method to tell the Query object that the query
/// string contains placeholders. Having done that, you call one of the
/// the many
/// \link mysqlpp::Query::execute(const SQLTypeAdapter&) exec*(), \endlink
/// \link mysqlpp::Query::store(const SQLTypeAdapter&) store*(), \endlink
/// or \link mysqlpp::Query::use(const SQLTypeAdapter&) use() \endlink
/// overloads that take SQLTypeAdapter objects.  There are 25 of each by
/// default, differing only in the number of STA objects they take.
/// (See \c lib/querydef.pl if you need to change the limit, or 
/// \c examples/tquery2.cpp for a way around it that doesn't require 
/// changing the library.)  Only the version taking a single STA object
/// is documented below, as to document all of them would just be
/// repetitive.  For each Query method that takes a single STA object,
/// there's a good chance there's a set of undocumented overloads that
/// take more of them for the purpose of filling out a template query.
///
/// See the user manual for more details about these options.

class MYSQLPP_EXPORT Query :
		public std::ostream,
		public OptionalExceptions
{
public:
	/// \brief Create a new query object attached to a connection.
	///
	/// This is the constructor used by mysqlpp::Connection::query().
	///
	/// \param c connection the finished query should be sent out on
	/// \param te if true, throw exceptions on errors
	/// \param qstr an optional initial query string
	Query(Connection* c, bool te = true, const char* qstr = 0);

	/// \brief Create a new query object as a copy of another.
	///
	/// This is \b not a traditional copy ctor!  Its only purpose is to
	/// make it possible to assign the return of Connection::query()
	/// to an empty Query object.  In particular, the stream buffer and
	/// template query stuff will be empty in the copy, regardless of
	/// what values they have in the original.
	Query(const Query& q);

	/// \brief Return the number of rows affected by the last query
	ulonglong affected_rows();

	/// \brief Return a SQL-escaped version of a character buffer
	///
	/// \param ps pointer to C++ string to hold escaped version; if
	/// original is 0, also holds the original data to be escaped
	/// \param original if given, pointer to the character buffer to
	/// escape instead of contents of *ps
	/// \param length if both this and original are given, number of
	/// characters to escape instead of ps->length()
	///
	/// \retval number of characters placed in *ps
	///
	/// This method has three basic operation modes:
	///
	/// - Pass just a pointer to a C++ string containing the original
	///   data to escape, plus act as receptacle for escaped version
	/// - Pass a pointer to a C++ string to receive escaped string plus
	///   a pointer to a C string to be escaped
	/// - Pass nonzero for all parameters, taking original to be a
	///   pointer to an array of char with given length; does not treat
	///   null characters as special
	///
	/// There's a degenerate fourth mode, where ps is zero: simply
	/// returns 0, because there is nowhere to store the result.
	///
	/// Note that if original is 0, we always ignore the length
	/// parameter even if it is nonzero.  Length always comes from
	/// ps->length() in this case.
	///
	/// ps is a pointer because if it were a reference, the other
	/// overload would be impossible to call: the compiler would
	/// complain that the two overloads are ambiguous because
	/// std::string has a char* conversion ctor. A nice bonus is that
	/// pointer syntax makes it clearer that the first parameter is an
	/// "out" parameter.
	///
	/// \see comments for escape_string(char*, const char*, size_t)
	/// for further details.
	size_t escape_string(std::string* ps, const char* original = 0,
			size_t length = 0) const;

	/// \brief Return a SQL-escaped version of the given character
	/// buffer
	///
	/// \param escaped character buffer to hold escaped version; must
	/// point to at least (length * 2 + 1) bytes
	/// \param original pointer to the character buffer to escape
	/// \param length number of characters to escape
	///
	/// \retval number of characters placed in escaped
	///
	/// This is part of Query because proper SQL escaping takes the
	/// database's current character set into account, which requires
	/// access to the Connection object the query will go out on.  Also,
	/// this function is very important to MySQL++'s Query stream
	/// manipulator mechanism, so it's more convenient for this method
	/// to live in Query rather than Connection.
	size_t escape_string(char* escaped, const char* original,
			size_t length) const;

	/// \brief Get the last error number that was set.
	///
	/// This just delegates to Connection::errnum().  Query has nothing
	/// extra to say, so use either, as makes sense in your program.
	int errnum() const;

	/// \brief Get the last error message that was set.
	///
	/// This just delegates to Connection::error().  Query has nothing
	/// extra to say, so use either, as makes sense in your program.
	const char* error() const;

	/// \brief Returns information about the most recently executed
	/// query.
	std::string info();

	/// \brief Get ID generated for an AUTO_INCREMENT column in the
	/// previous INSERT query.
	///
	/// \retval 0 if the previous query did not generate an ID.  Use
	/// the SQL function LAST_INSERT_ID() if you need the last ID
	/// generated by any query, not just the previous one.  This
	/// applies to stored procedure calls because this function returns
	/// the ID generated by the last query, which was a CALL statement,
	/// and CALL doesn't generate IDs.  You need to use LAST_INSERT_ID()
	/// to get the ID in this case.
	ulonglong insert_id();

	/// \brief Assign another query's state to this object
	///
	/// The same caveats apply to this operator as apply to the copy
	/// ctor.
	Query& operator=(const Query& rhs);

	/// \brief Test whether the object has experienced an error condition
	///
	/// Allows for code constructs like this:
	///
	/// \code
	///	Query q = conn.query();
	///	.... use query object
	///	if (q) {
	///	    ... no problems in using query object
	///	}
	///	else {
	///	    ... an error has occurred
	///	}
	/// \endcode
	///
	/// This method returns false if either the Query object or its
	/// associated Connection object has seen an error condition since
	/// the last operation.
	operator void*() const;

	/// \brief Treat the contents of the query string as a template
	/// query.
	///
	/// This method sets up the internal structures used by all of the
	/// other members that accept template query parameters.  See the
	/// "Template Queries" chapter in the user manual for more
	/// information.
	void parse();

	/// \brief Reset the query object so that it can be reused.
	///
	/// As of v3.0, Query objects auto-reset upon query execution unless
	/// you've set it up for making template queries.  (It can't auto-reset
	/// in that situation, because it would forget the template info.)
	/// Therefore, the only time you must call this is if you have a Query
	/// object set up for making template queries, then want to build
	/// queries using one of the other methods.  (Static strings, SSQLS,
	/// or the stream interface.)
	void reset();

	/// \brief Get built query as a C++ string
	std::string str() { return str(template_defaults); }

	/// \brief Get built query as a C++ string with template query
	/// parameter substitution.
	///
	/// \param arg0 the value to substitute for the first template query
	/// parameter; because SQLTypeAdapter implicitly converts from many
	/// different data types, this method is very flexible in what it
	/// accepts as a parameter.  You shouldn't have to use the
	/// SQLTypeAdapter data type directly in your code.
	///
	/// There many more overloads of this type (25 total, by default;
	/// see \c lib/querydef.pl), each taking one more SQLTypeAdapter object
	/// than the previous one.  See the template query overview above
	/// for more about this topic.
	std::string str(const SQLTypeAdapter& arg0)
			{ return str(SQLQueryParms() << arg0); }

	/// \brief Get built query as a null-terminated C++ string
	///
	/// \param p template query parameters to use, overriding the ones
	/// this object holds, if any
	std::string str(SQLQueryParms& p);

	/// \brief Execute a built-up query
	///
	/// Same as exec(), except that it uses the query string built up
	/// within the query object already instead of accepting a query
	/// string from the caller.
	///
	/// \return true if query was executed successfully
	///
	/// \sa exec(const std::string& str), execute(), store(),
	/// storein(), and use()
	bool exec() { return exec(str(template_defaults)); }

	/// \brief Execute a query
	///
	/// Same as execute(), except that it only returns a flag indicating
	/// whether the query succeeded or not.  It is basically a thin
	/// wrapper around the C API function \c mysql_real_query().
	///
	/// \param str the query to execute
	///
	/// \return true if query was executed successfully
	///
	/// \sa execute(), store(), storein(), and use()
	bool exec(const std::string& str);

	/// \brief Execute built-up query
	///
	/// Use one of the execute() overloads if you don't expect the
	/// server to return a result set. For instance, a DELETE query.
	/// The returned SimpleResult object contains status information from
	/// the server, such as whether the query succeeded, and if so how
	/// many rows were affected.
	///
	/// This overloaded version of execute() simply executes the query
	/// that you have built up in the object in some way. (For instance,
	/// via the insert() method, or by using the object's stream
	/// interface.)
	///
	/// \return SimpleResult status information about the query
	///
	/// \sa exec(), store(), storein(), and use()
	SimpleResult execute() { return execute(str(template_defaults)); }

	/// \brief Execute template query using given parameters.
	///
	/// This method should only be used by code that doesn't know,
	/// at compile time, how many parameters it will have.  This is
	/// useful within the library, and also for code that builds
	/// template queries dynamically, at run time.
	///
	/// \param p parameters to use in the template query.
	SimpleResult execute(SQLQueryParms& p);

	/// \brief Execute a query that returns no rows
	///
	/// \param str if this object is set up as a template query, this is
	/// the value to substitute for the first template query parameter;
	/// else, it is the SQL query string to execute
	///
	/// Because SQLTypeAdapter can be initialized from either a C string
	/// or a C++ string, this overload accepts query strings in either
	/// form.  Beware, SQLTypeAdapter also accepts many other data types
	/// (this is its \e raison \e d'etre), so it will let you write code
	/// that compiles but results in bogus SQL queries.
	///
	/// To support template queries, there many more overloads of this
	/// type (25 total, by default; see \c lib/querydef.pl), each taking
	/// one more SQLTypeAdapter object than the previous one.  See the
	/// template query overview above for more about this topic.
	SimpleResult execute(const SQLTypeAdapter& str);

	/// \brief Execute query in a known-length string of characters.
	/// This can include null characters.
	///
	/// Executes the query immediately, and returns the results.
	SimpleResult execute(const char* str, size_t len);

	/// \brief Execute a query that can return rows, with access to
	/// the rows in sequence
	/// 
	/// Use one of the use() overloads if memory efficiency is
	/// important.  They return an object that can walk through
	/// the result records one by one, without fetching the entire
	/// result set from the server.  This is superior to store()
	/// when there are a large number of results; store() would have to
	/// allocate a large block of memory to hold all those records,
	/// which could cause problems.
	///
	/// A potential downside of this method is that MySQL database
	/// resources are tied up until the result set is completely
	/// consumed.  Do your best to walk through the result set as
	/// expeditiously as possible.
	///
	/// The name of this method comes from the MySQL C API function
	/// that initiates the retrieval process, \c mysql_use_result().
	/// This method is implemented in terms of that function.
	///
	/// This function has the same set of overloads as execute().
	///
	/// \return UseQueryResult object that can walk through result set serially
	///
	/// \sa exec(), execute(), store() and storein()
	UseQueryResult use() { return use(str(template_defaults)); }

	/// \brief Execute a template query that can return rows, with
	/// access to the rows in sequence
	///
	/// This method should only be used by code that doesn't know,
	/// at compile time, how many parameters it will have.  This is
	/// useful within the library, and also for code that builds
	/// template queries dynamically, at run time.
	///
	/// \param p parameters to use in the template query.
	UseQueryResult use(SQLQueryParms& p);

	/// \brief Execute a query that can return rows, with access to
	/// the rows in sequence
	///
	/// \param str if this object is set up as a template query, this is
	/// the value to substitute for the first template query parameter;
	/// else, it is the SQL query string to execute
	///
	/// Because SQLTypeAdapter can be initialized from either a C string
	/// or a C++ string, this overload accepts query strings in either
	/// form.  Beware, SQLTypeAdapter also accepts many other data types
	/// (this is its \e raison \e d'etre), so it will let you write code
	/// that compiles but results in bogus SQL queries.
	///
	/// To support template queries, there many more overloads of this
	/// type (25 total, by default; see \c lib/querydef.pl), each taking
	/// one more SQLTypeAdapter object than the previous one.  See the
	/// template query overview above for more about this topic.
	UseQueryResult use(const SQLTypeAdapter& str);

	/// \brief Execute a query that can return rows, with access to
	/// the rows in sequence
	///
	/// This overload is for situations where you have the query in a
	/// C string and have its length already.  If you want to execute
	/// a query in a null-terminated C string or have the query string
	/// in some other form, you probably want to call
	/// use(const SQLTypeAdapter&) instead.  SQLTypeAdapter converts
	/// from plain C strings and other useful data types implicitly.
	UseQueryResult use(const char* str, size_t len);

	/// \brief Execute a query that can return a result set
	///
	/// Use one of the store() overloads to execute a query and retrieve
	/// the entire result set into memory.  This is useful if you
	/// actually need all of the records at once, but if not, consider
	/// using one of the use() methods instead, which returns the results
	/// one at a time, so they don't allocate as much memory as store().
	///
	/// You must use store(), storein() or use() for \c SELECT, \c SHOW,
	/// \c DESCRIBE and \c EXPLAIN queries.  You can use these functions
	/// with other query types, but since they don't return a result
	/// set, exec() and execute() are more efficient.
	///
	/// The name of this method comes from the MySQL C API function it
	/// is implemented in terms of, \c mysql_store_result().
	///
	/// This function has the same set of overloads as execute().
	///
	/// \return StoreQueryResult object containing entire result set
	///
	/// \sa exec(), execute(), storein(), and use()
	StoreQueryResult store() { return store(str(template_defaults)); }

	/// \brief Store results from a template query using given parameters.
	///
	/// This method should only be used by code that doesn't know,
	/// at compile time, how many parameters it will have.  This is
	/// useful within the library, and also for code that builds
	/// template queries dynamically, at run time.
	///
	/// \param p parameters to use in the template query.
	StoreQueryResult store(SQLQueryParms& p);

	/// \brief Execute a query that can return rows, returning all
	/// of the rows in a random-access container
	///
	/// \param str if this object is set up as a template query, this is
	/// the value to substitute for the first template query parameter;
	/// else, it is the SQL query string to execute
	///
	/// Because SQLTypeAdapter can be initialized from either a C string
	/// or a C++ string, this overload accepts query strings in either
	/// form.  Beware, SQLTypeAdapter also accepts many other data types
	/// (this is its \e raison \e d'etre), so it will let you write code
	/// that compiles but results in bogus SQL queries.
	///
	/// To support template queries, there many more overloads of this
	/// type (25 total, by default; see \c lib/querydef.pl), each taking
	/// one more SQLTypeAdapter object than the previous one.  See the
	/// template query overview above for more about this topic.
	StoreQueryResult store(const SQLTypeAdapter& str);

	/// \brief Execute a query that can return rows, returning all
	/// of the rows in a random-access container
	///
	/// This overload is for situations where you have the query in a
	/// C string and have its length already.  If you want to execute
	/// a query in a null-terminated C string or have the query string
	/// in some other form, you probably want to call
	/// store(const SQLTypeAdapter&) instead.  SQLTypeAdapter converts
	/// from plain C strings and other useful data types implicitly.
	StoreQueryResult store(const char* str, size_t len);

	/// \brief Execute a query, and call a functor for each returned row
	///
	/// This method wraps a use() query, calling the given functor for
	/// every returned row.  It is analogous to STL's for_each()
	/// algorithm, but instead of iterating over some range within a
	/// container, it iterates over a result set produced by a query.
	///
	/// \param query the query string
	/// \param fn the functor called for each row
	/// \return a copy of the passed functor
	template <typename Function>
	Function for_each(const SQLTypeAdapter& query, Function fn)
	{	
		mysqlpp::UseQueryResult res = use(query);
		if (res) {
			mysqlpp::NoExceptions ne(res);
			while (mysqlpp::Row row = res.fetch_row()) {
				fn(row);
			}
		}

		return fn;
	}

	/// \brief Execute the query, and call a functor for each returned row
	///
	/// Just like for_each(const SQLTypeAdapter&, Function), but it uses
	/// the query string held by the Query object already
	///
	/// \param fn the functor called for each row
	/// \return a copy of the passed functor
	template <typename Function>
	Function for_each(Function fn)
	{	
		mysqlpp::UseQueryResult res = use();
		if (res) {
			mysqlpp::NoExceptions ne(res);
			while (mysqlpp::Row row = res.fetch_row()) {
				fn(row);
			}
		}

		return fn;
	}

	/// \brief Run a functor for every row in a table
	///
	/// Just like for_each(Function), except that it builds a
	/// "select * from TABLE" query using the SQL table name from
	/// the SSQLS instance you pass.
	///
	/// \param ssqls the SSQLS instance to get a table name from
	/// \param fn the functor called for each row
	///
	/// \return a copy of the passed functor
	template <class SSQLS, typename Function>
	Function for_each(const SSQLS& ssqls, Function fn)
	{	
		std::string query("select * from ");
		query += ssqls.table();
		mysqlpp::UseQueryResult res = use(query);
		if (res) {
			mysqlpp::NoExceptions ne(res);
			while (mysqlpp::Row row = res.fetch_row()) {
				fn(row);
			}
		}

		return fn;
	}

	/// \brief Execute a query, conditionally storing each row in a
	/// container
	///
	/// This method wraps a use() query, calling the given functor for
	/// every returned row, and storing the results in the given
	/// sequence container if the functor returns true.
	///
	/// This is analogous to the STL copy_if() algorithm, except that
	/// the source rows come from a database query instead of another
	/// container.  (copy_if() isn't a standard STL algorithm, but only
	/// due to an oversight by the standardization committee.)  This
	/// fact may help you to remember the order of the parameters: the
	/// container is the destination, the query is the source, and the
	/// functor is the predicate; it's just like an STL algorithm.
	///
	/// \param con the destination container; needs a push_back() method
	/// \param query the query string
	/// \param fn the functor called for each row
	/// \return a copy of the passed functor
	template <class Sequence, typename Function>
	Function store_if(Sequence& con, const SQLTypeAdapter& query, Function fn)
	{	
		mysqlpp::UseQueryResult res = use(query);
		if (res) {
			mysqlpp::NoExceptions ne(res);
			while (mysqlpp::Row row = res.fetch_row()) {
				if (fn(row)) {
					con.push_back(row);
				}
			}
		}

		return fn;
	}

	/// \brief Pulls every row in a table, conditionally storing each
	/// one in a container
	///
	/// Just like store_if(Sequence&, const SQLTypeAdapter&, Function), but
	/// it uses the SSQLS instance to construct a "select * from TABLE"
	/// query, using the table name field in the SSQLS.
	///
	/// \param con the destination container; needs a push_back() method
	/// \param ssqls the SSQLS instance to get a table name from
	/// \param fn the functor called for each row
	/// \return a copy of the passed functor
	template <class Sequence, class SSQLS, typename Function>
	Function store_if(Sequence& con, const SSQLS& ssqls, Function fn)
	{	
		std::string query("select * from ");
		query += ssqls.table();
		mysqlpp::UseQueryResult res = use(query);
		if (res) {
			mysqlpp::NoExceptions ne(res);
			while (mysqlpp::Row row = res.fetch_row()) {
				if (fn(row)) {
					con.push_back(row);
				}
			}
		}

		return fn;
	}

	/// \brief Execute the query, conditionally storing each row in a
	/// container
	///
	/// Just like store_if(Sequence&, const SQLTypeAdapter&, Function), but
	/// it uses the query string held by the Query object already
	///
	/// \param con the destination container; needs a push_back() method
	/// \param fn the functor called for each row
	/// \return a copy of the passed functor
	template <class Sequence, typename Function>
	Function store_if(Sequence& con, Function fn)
	{	
		mysqlpp::UseQueryResult res = use();
		if (res) {
			mysqlpp::NoExceptions ne(res);
			while (mysqlpp::Row row = res.fetch_row()) {
				if (fn(row)) {
					con.push_back(row);
				}
			}
		}

		return fn;
	}

	/// \brief Return next result set, when processing a multi-query
	///
	/// There are two cases where you'd use this function instead of
	/// the regular store() functions.
	/// 
	/// First, when handling the result of executing multiple queries
	/// at once.  (See <a
	/// href="http://dev.mysql.com/doc/mysql/en/c-api-multiple-queries.html">this
	/// page</a> in the MySQL documentation for details.) 
	///
	/// Second, when calling a stored procedure, MySQL can return the
	/// result as a set of results.
	///
	/// In either case, you must consume all results before making
	/// another MySQL query, even if you don't care about the remaining
	/// results or result sets.
	///
	/// As the MySQL documentation points out, you must set the
	/// MYSQL_OPTION_MULTI_STATEMENTS_ON flag on the connection in order
	/// to use this feature.  See Connection::set_option().
	///
	/// Multi-queries only exist in MySQL v4.1 and higher.  Therefore,
	/// this function just wraps store() when built against older API
	/// libraries.
	///
	/// \return StoreQueryResult object containing the next result set.
	StoreQueryResult store_next();

	/// \brief Return whether more results are waiting for a multi-query
	/// or stored procedure response.
	///
	/// If this function returns true, you must call store_next() to
	/// fetch the next result set before you can execute more queries.
	///
	/// Wraps mysql_more_results() in the MySQL C API.  That function
	/// only exists in MySQL v4.1 and higher.  Therefore, this function
	/// always returns false when built against older API libraries.
	///
	/// \return true if another result set exists
	bool more_results();

	/// \brief Execute a query, storing the result set in an STL
	/// sequence container.
	///
	/// This function works much like store() from the caller's
	/// perspective, because it returns the entire result set at once.
	/// It's actually implemented in terms of use(), however, so that
	/// memory for the result set doesn't need to be allocated twice.
	///
	/// There are many overloads for this function, pretty much the same
	/// as for execute(), except that there is a Container parameter at
	/// the front of the list.  So, you can pass a container and a query
	/// string, or a container and template query parameters.
	///
	/// \param con any STL sequence container, such as \c std::vector
	///
	/// \sa exec(), execute(), store(), and use()
	template <class Sequence>
	void storein_sequence(Sequence& con)
	{
		storein_sequence(con, str(template_defaults));
	}

	/// \brief Executes a query, storing the result rows in an STL
	/// sequence container.
	///
	/// \param con the container to store the results in
	///
	/// \param s if Query is set up as a template query, this is the value
	/// to substitute for the first template query parameter; else, the
	/// SQL query string
	///
	/// There many more overloads of this type (25 total, by default;
	/// see \c lib/querydef.pl), each taking one more SQLTypeAdapter object
	/// than the previous one.  See the template query overview above
	/// for more about this topic.
	template <class Sequence>
	void storein_sequence(Sequence& con, const SQLTypeAdapter& s)
	{
		UseQueryResult result = use(s);
		while (1) {
			MYSQL_ROW d = result.fetch_raw_row();
			if (!d)
				break;
			Row row(d, &result, result.fetch_lengths(),
					throw_exceptions());
			if (!row)
				break;
			con.push_back(typename Sequence::value_type(row));
		}
	}

	/// \brief Execute template query using given parameters, storing
	/// the results in a sequence type container.
	///
	/// This method should only be used by code that doesn't know,
	/// at compile time, how many parameters it will have.  This is
	/// useful within the library, and also for code that builds
	/// template queries dynamically, at run time.
	///
	/// \param con container that will receive the results
	/// \param p parameters to use in the template query.
	template <class Seq>
	void storein_sequence(Seq& con, SQLQueryParms& p)
	{
		storein_sequence(con, str(p));
	}

	/// \brief Execute a query, storing the result set in an STL
	/// associative container.
	///
	/// The same thing as storein_sequence(), except that it's used with
	/// associative STL containers, such as \c std::set.  Other than
	/// that detail, that method's comments apply equally well to this
	/// one.
	template <class Set>
	void storein_set(Set& con)
	{
		storein_set(con, str(template_defaults));
	}

	/// \brief Executes a query, storing the result rows in an STL
	/// set-associative container.
	///
	/// \param con the container to store the results in
	///
	/// \param s if Query is set up as a template query, this is the value
	/// to substitute for the first template query parameter; else, the
	/// SQL query string
	///
	/// There many more overloads of this type (25 total, by default;
	/// see \c lib/querydef.pl), each taking one more SQLTypeAdapter object
	/// than the previous one.  See the template query overview above
	/// for more about this topic.
	template <class Set>
	void storein_set(Set& con, const SQLTypeAdapter& s)
	{
		UseQueryResult result = use(s);
		while (1) {
			MYSQL_ROW d = result.fetch_raw_row();
			if (!d)
				return;
			Row row(d, &result, result.fetch_lengths(),
					throw_exceptions());
			if (!row)
				break;
			con.insert(typename Set::value_type(row));
		}
	}

	/// \brief Execute template query using given parameters, storing
	/// the results in a set type container.
	///
	/// This method should only be used by code that doesn't know,
	/// at compile time, how many parameters it will have.  This is
	/// useful within the library, and also for code that builds
	/// template queries dynamically, at run time.
	///
	/// \param con container that will receive the results
	/// \param p parameters to use in the template query.
	template <class Set>
	void storein_set(Set& con, SQLQueryParms& p)
	{
		storein_set(con, str(p));
	}

	/// \brief Execute a query, and store the entire result set
	/// in an STL container.
	///
	/// This is a set of specialized template functions that call either
	/// storein_sequence() or storein_set(), depending on the type of
	/// container you pass it. It understands \c std::vector, \c deque,
	/// \c list, \c slist (a common C++ library extension), \c set,
	/// and \c multiset.
	///
	/// Like the functions it wraps, this is actually an overloaded set
	/// of functions. See the other functions' documentation for details.
	///
	/// Use this function if you think you might someday switch your
	/// program from using a set-associative container to a sequence
	/// container for storing result sets, or vice versa.
	///
	/// See exec(), execute(), store(), and use() for alternative
	/// query execution mechanisms.
	template <class Container>
	void storein(Container& con)
	{
		storein(con, str(template_defaults));
	}

	/// \brief Store template query results into a container
	///
	/// This method is not intended to be used directly.  It is part
	/// of the call chain in processing calls to one of the many
	/// storein() overloads that take a container and one or more
	/// SQLTypeAdapter parameters.
	template <class T>
	void storein(T& con, SQLQueryParms& p)
	{
		storein(con, str(p));
	}

	/// \brief Specialization of storein_sequence() for \c std::vector
	template <class T>
	void storein(std::vector<T>& con, const SQLTypeAdapter& s)
	{
		storein_sequence(con, s);
	}

	/// \brief Specialization of storein_sequence() for \c std::deque
	template <class T>
	void storein(std::deque<T>& con, const SQLTypeAdapter& s)
	{
		storein_sequence(con, s);
	}

	/// \brief Specialization of storein_sequence() for \c std::list
	template <class T>
	void storein(std::list<T>& con, const SQLTypeAdapter& s)
	{
		storein_sequence(con, s);
	}

#if defined(HAVE_EXT_SLIST)
	/// \brief Specialization of storein_sequence() for g++ STL
	/// extension \c slist
	template <class T>
	void storein(__gnu_cxx::slist<T>& con, const SQLTypeAdapter& s)
	{
		storein_sequence(con, s);
	}
#elif defined(HAVE_GLOBAL_SLIST)
	/// \brief Specialization of storein_sequence() for STL
	/// extension \c slist
	///
	/// This is primarily for older versions of g++, which put \c slist
	/// in the global namespace.  This is a common language extension,
	/// so this may also work for other compilers.
	template <class T>
	void storein(slist<T>& con, const SQLTypeAdapter& s)
	{
		storein_sequence(con, s);
	}
#elif defined(HAVE_STD_SLIST)
	/// \brief Specialization of storein_sequence() for STL
	/// extension \c slist
	///
	/// This is for those benighted compilers that include an \c slist
	/// implementation, but erroneously put it in the \c std namespace!
	template <class T>
	void storein(std::slist<T>& con, const SQLTypeAdapter& s)
	{
		storein_sequence(con, s);
	}
#endif

	/// \brief Specialization of storein_set() for \c std::set
	template <class T>
	void storein(std::set<T>& con, const SQLTypeAdapter& s)
	{
		storein_set(con, s);
	}

	/// \brief Specialization of storein_set() for \c std::multiset
	template <class T>
	void storein(std::multiset<T>& con, const SQLTypeAdapter& s)
	{
		storein_set(con, s);
	}

	/// \brief Replace an existing row's data with new data.
	///
	/// This function builds an UPDATE SQL query using the new row data
	/// for the SET clause, and the old row data for the WHERE clause.
	/// One uses it with MySQL++'s Specialized SQL Structures mechanism.
	///
	/// \param o old row
	/// \param n new row
	///
	/// \sa insert(), replace()
	template <class T>
	Query& update(const T& o, const T& n)
	{
		reset();

		// Cast required for VC++ 2003 due to error in overloaded operator
		// lookup logic.  For an explanation of the problem, see:
		// http://groups-beta.google.com/group/microsoft.public.vc.stl/browse_thread/thread/9a68d84644e64f15
		MYSQLPP_QUERY_THISPTR << std::setprecision(16) <<
				"UPDATE " << o.table() << " SET " << n.equal_list() <<
				" WHERE " << o.equal_list(" AND ", sql_use_compare);
		return *this;
	}

	/// \brief Insert a new row.
	///
	/// This function builds an INSERT SQL query.  One uses it with
	/// MySQL++'s Specialized SQL Structures mechanism.
	///
	/// \param v new row
	///
	/// \sa replace(), update()
	template <class T>
	Query& insert(const T& v)
	{
		reset();

		MYSQLPP_QUERY_THISPTR << std::setprecision(16) <<
				"INSERT INTO " << v.table() << " (" <<
				v.field_list() << ") VALUES (" <<
				v.value_list() << ')';
		return *this;
	}

	/// \brief Insert multiple new rows.
	///
	/// Builds an INSERT SQL query using items from a range within an
	/// STL container.  Insert the entire contents of the container by
	/// using the begin() and end() iterators of the container as
	/// parameters to this function.
	///
	/// \param first iterator pointing to first element in range to
	///    insert
	/// \param last iterator pointing to one past the last element to
	///    insert
	///
	/// \sa replace(), update()
	template <class Iter>
	Query& insert(Iter first, Iter last)
	{
		reset();
		if (first == last) {
			return *this;	// empty set!
		}
		
		MYSQLPP_QUERY_THISPTR << std::setprecision(16) <<
				"INSERT INTO " << first->table() << " (" <<
				first->field_list() << ") VALUES (" <<
				first->value_list() << ')';

		Iter it = first + 1;
		while (it != last) {
			MYSQLPP_QUERY_THISPTR << ",(" << it->value_list() << ')';
			++it;
		}

		return *this;
	}

	/// \brief Insert new row unless there is an existing row that
	/// matches on a unique index, in which case we replace it.
	///
	/// This function builds a REPLACE SQL query.  One uses it with
	/// MySQL++'s Specialized SQL Structures mechanism.
	///
	/// \param v new row
	///
	/// \sa insert(), update()
	template <class T>
	Query& replace(const T& v)
	{
		reset();

		MYSQLPP_QUERY_THISPTR << std::setprecision(16) <<
				"REPLACE INTO " << v.table() << " (" <<
				v.field_list() << ") VALUES (" << v.value_list() << ')';
		return *this;
	}

#if !defined(DOXYGEN_IGNORE)
	// Declare the remaining overloads.  These are hidden down here partly
	// to keep the above code clear, but also so that we may hide them
	// from Doxygen, which gets confused by macro instantiations that look
	// like method declarations.
	mysql_query_define0(std::string, str)
	mysql_query_define0(SimpleResult, execute)
	mysql_query_define0(StoreQueryResult, store)
	mysql_query_define0(UseQueryResult, use)
	mysql_query_define1(storein_sequence)
	mysql_query_define1(storein_set)
	mysql_query_define1(storein)
#endif // !defined(DOXYGEN_IGNORE)

	/// \brief The default template parameters
	///
	/// Used for filling in parameterized queries.
	SQLQueryParms template_defaults;

private:
	friend class SQLQueryParms;

	/// \brief Connection to send queries through
	Connection* conn_;

	/// \brief If true, last query succeeded
	bool copacetic_;

	/// \brief List of template query parameters
	std::vector<SQLParseElement> parse_elems_;

	/// \brief Maps template parameter position values to the
	/// corresponding parameter name.
	std::vector<std::string> parsed_names_;

	/// \brief Maps template parameter names to their position value.
	std::map<std::string, short int> parsed_nums_;

	/// \brief String buffer for storing assembled query
	std::stringbuf sbuffer_;

	/// \brief Process a parameterized query list.
	void proc(SQLQueryParms& p);

	SQLTypeAdapter* pprepare(char option, SQLTypeAdapter& S, bool replace = true);
};


/// \brief Insert raw query string into the given stream.
///
/// This is just syntactic sugar for Query::str(void)
inline std::ostream& operator <<(std::ostream& os, Query& q)
{
	return os << q.str();
}


} // end namespace mysqlpp

#endif // !defined(MYSQLPP_QUERY_H)

Changes to examples/tquery1.cpp.

1
2
3
4

5
6
7
8
9
10
11
12
13
/***********************************************************************
 tquery1.cpp - Example similar to ssqls3.cpp, except that it uses
	template queries instead of SSQLS.


 Copyright (c) 1998 by Kevin Atkinson, (c) 1999-2001 by MySQL AB, and
 (c) 2004-2009 by Educational Technology Resources, Inc.  Others may
 also hold copyrights on code in this file.  See the CREDITS.txt file
 in the top directory of the distribution for details.

 This file is part of MySQL++.

 MySQL++ is free software; you can redistribute it and/or modify it
 under the terms of the GNU Lesser General Public License as published
|
|
<

>

|







1
2

3
4
5
6
7
8
9
10
11
12
13
/// \file comparable.h
/// \brief Declares the Comparable<T> mixin


/***********************************************************************
 Copyright (c) 1998 by Kevin Atkinson, (c) 1999-2001 by MySQL AB, and
 (c) 2004-2008 by Educational Technology Resources, Inc.  Others may
 also hold copyrights on code in this file.  See the CREDITS.txt file
 in the top directory of the distribution for details.

 This file is part of MySQL++.

 MySQL++ is free software; you can redistribute it and/or modify it
 under the terms of the GNU Lesser General Public License as published
21
22
23
24
25
26
27


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
56
57
58
59
60
61


62
63
64
65
66
67
68
69
70
71
72
73

74
75
76

77
78
79

80
81
82
83

84
85
86









87
88

89



90
91
92
93


 You should have received a copy of the GNU Lesser General Public
 License along with MySQL++; if not, write to the Free Software
 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
 USA
***********************************************************************/



#include "cmdline.h"

#include "printdata.h"









#include <iostream>




using namespace std;

int
main(int argc, char *argv[])


{
	// Get database access parameters from command line
	mysqlpp::examples::CommandLine cmdline(argc, argv);
	if (!cmdline) {
		return 1;
	}

	try {
		// Establish the connection to the database server.
		mysqlpp::Connection con(mysqlpp::examples::db_name,
				cmdline.server(), cmdline.user(), cmdline.pass());



		// Build a template query to retrieve a stock item given by
		// item name.
		mysqlpp::Query query = con.query(
				"select * from stock where item = %0q");
		query.parse();

		// Retrieve an item added by resetdb; it won't be there if
		// tquery* or ssqls3 is run since resetdb.
		mysqlpp::StoreQueryResult res1 = query.store("Nürnberger Brats");
		if (res1.empty()) {
			throw mysqlpp::BadQuery("UTF-8 bratwurst item not found in "
					"table, run resetdb");
		}



		// Replace the proper German name with a 7-bit ASCII
		// approximation using a different template query.
		query.reset();		// forget previous template query data
		query << "update stock set item = %0q where item = %1q";
		query.parse();
		mysqlpp::SimpleResult res2 = query.execute("Nuerenberger Bratwurst",
				res1[0][0].c_str());

		// Print the new table contents.
		print_stock_table(query);
	}

	catch (const mysqlpp::BadQuery& er) {
		// Handle any query errors
		cerr << "Query error: " << er.what() << endl;

		return -1;
	}
	catch (const mysqlpp::BadConversion& er) {

		// Handle bad conversions
		cerr << "Conversion error: " << er.what() << endl <<
				"\tretrieved data size: " << er.retrieved <<
				", actual size: " << er.actual_size << endl;

		return -1;
	}
	catch (const mysqlpp::Exception& er) {









		// Catch-all for any other MySQL++ exceptions
		cerr << "Error: " << er.what() << endl;

		return -1;



	}

	return 0;
}








>
>
|
>
|
>
>
>
>
>
>
>
>
|
<
>
>
>
|
|
|
|
<
>
>
|
<
<
<
|


<
<
<
<
>
>
|
<
<
<
<
|
|
<
<
<
<
<
<
|
>
>
|
<
<
<
<
|
<
<
|
<
<
|
>
|
<
<
>
|

|
>
|
<
<
<
>
|

|
>
>
>
>
>
>
>
>
>
|
|
>
|
>
>
>
|
|
<
|
>
21
22
23
24
25
26
27
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
56
57




58
59






60
61
62
63




64


65


66
67
68


69
70
71
72
73
74



75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96

97
98

 You should have received a copy of the GNU Lesser General Public
 License along with MySQL++; if not, write to the Free Software
 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
 USA
***********************************************************************/

#if !defined(MYSQLPP_COMPARABLE_H)
#define MYSQLPP_COMPARABLE_H

namespace mysqlpp {

/// \brief Mix-in that gives its subclass a full set of comparison
/// operators.
///
/// Simply by inheriting publically from this and implementing
/// compare(), the subclass gains a full set of comparison operators,
/// because all of the operators are implemented in terms of compare().
template <class T>
class Comparable
{

public:
	/// \brief Returns true if "other" is equal to this object
	bool operator ==(const T& other) const
	{
		return !compare(other);
	}


	/// \brief Returns true if "other" is not equal to this object
	bool operator !=(const T& other) const
	{



		return compare(other);
	}





	/// \brief Returns true if "other" is less than this object
	bool operator <(const T& other) const
	{




		return compare(other) < 0;
	}







	/// \brief Returns true if "other" is less than or equal to this object
	bool operator <=(const T& other) const
	{




		return compare(other) <= 0;


	}



	/// \brief Returns true if "other" is greater than this object
	bool operator >(const T& other) const


	{
		return compare(other) > 0;
	}

	/// \brief Returns true if "other" is greater than or equal to this object
	bool operator >=(const T& other) const



	{
		return compare(other) >= 0;
	}

protected:
	/// \brief Destroy object
	///
	/// This class has nothing to destroy, but declaring the dtor
	/// virtual placates some compilers set to high warning levels.
	/// Protecting it ensures you can't delete subclasses through base
	/// class pointers, which makes no sense because this class isn't
	/// made for polymorphism.  It's just a mixin.
	virtual ~Comparable() { }

	/// \brief Compare this object to another of the same type
	///
	/// Returns < 0 if this object is "before" the other, 0 of they are
	/// equal, and > 0 if this object is "after" the other.
	virtual int compare(const T& other) const = 0;
};

}


#endif // !defined(MYSQLPP_COMPARABLE_H)

Changes to examples/tquery2.cpp.

1
2
3
4
5
6
7
8
9

10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
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







56
57
58
59




60
61
62









63


64
65

66


67











68
69

70




71








72
73










74




75




76
77
78
79

80




81
82
83


84
85
86


87




88
89


90
91

92
93

94








95
96
97
98

99
/***********************************************************************
 tquery2.cpp - Same as tquery1.cpp, except that it passes the template
	query parameters in a SQLQueryParms object, instead of separately.
	This is useful when the calling code doesn't know in advance how
	many parameters there will be.  This is most likely because the
	templates are coming from somewhere else, or being generated.

 Copyright (c) 1998 by Kevin Atkinson, (c) 1999-2001 by MySQL AB, and
 (c) 2004-2009 by Educational Technology Resources, Inc.  Others may

 also hold copyrights on code in this file.  See the CREDITS.txt file
 in the top directory of the distribution for details.

 This file is part of MySQL++.

 MySQL++ is free software; you can redistribute it and/or modify it
 under the terms of the GNU Lesser General Public License as published
 by the Free Software Foundation; either version 2.1 of the License, or
 (at your option) any later version.

 MySQL++ is distributed in the hope that it will be useful, but WITHOUT
 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
 License for more details.

 You should have received a copy of the GNU Lesser General Public
 License along with MySQL++; if not, write to the Free Software
 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
 USA
***********************************************************************/

#include "cmdline.h"

#include "printdata.h"

#include <iostream>


using namespace std;

int






main(int argc, char *argv[])


{






	// Get database access parameters from command line




	mysqlpp::examples::CommandLine cmdline(argc, argv);
	if (!cmdline) {
		return 1;

	}

	try {
		// Establish the connection to the database server.




		mysqlpp::Connection con(mysqlpp::examples::db_name,




				cmdline.server(), cmdline.user(), cmdline.pass());










		// Build a template query to retrieve a stock item given by
		// item name.



		mysqlpp::Query query = con.query(
				"select * from stock where item = %0q");







		query.parse();

		// Retrieve an item added by resetdb; it won't be there if
		// tquery* or ssqls3 is run since resetdb.




		mysqlpp::SQLQueryParms sqp;
		sqp << "Nürnberger Brats";
		mysqlpp::StoreQueryResult res1 = query.store(sqp);









		if (res1.empty()) {


			throw mysqlpp::BadQuery("UTF-8 bratwurst item not found in "
					"table, run resetdb");

		}














		// Replace the proper German name with a 7-bit ASCII
		// approximation using a different template query.

		query.reset();		// forget previous template query info




		query << "update stock set item = %0q where item = %1q";








		query.parse();
		sqp.clear();










		sqp << "Nuerenberger Bratwurst" << res1[0][0].c_str();




		mysqlpp::SimpleResult res2 = query.execute(sqp);





		// Print the new table contents.
		print_stock_table(query);
	}

	catch (const mysqlpp::BadQuery& er) {




		// Handle any query errors
		cerr << "Query error: " << er.what() << endl;
		return -1;


	}
	catch (const mysqlpp::BadConversion& er) {
		// Handle bad conversions


		cerr << "Conversion error: " << er.what() << endl <<




				"\tretrieved data size: " << er.retrieved <<
				", actual size: " << er.actual_size << endl;


		return -1;
	}

	catch (const mysqlpp::Exception& er) {
		// Catch-all for any other MySQL++ exceptions

		cerr << "Error: " << er.what() << endl;








		return -1;
	}

	return 0;

}

|
<
<
<
<

<
|
>
|
|



















|
>
|

|
>

|

|
>
>
>
>
>
>
|
>
>

>
>
>
>
>
>
|
>
>
>
>
|
|
|
>
|

|
|
>
>
>
>
|
>
>
>
>
|
>
>
>
>
|
>
>
>
>
>
|
|
>
>
>
|
|
>
>
>
>
>
>
>
|
|
|
|
>
>
>
>
|
<
<
>
>
>
>
>
>
>
>
>
|
>
>
|
|
>
|
>
>
|
>
>
>
>
>
>
>
>
>
>
>
|
|
>
|
>
>
>
>
|
>
>
>
>
>
>
>
>
|
|
>
>
>
>
>
>
>
>
>
>
|
>
>
>
>
|
>
>
>
>
|
<
<

>
|
>
>
>
>
|
<
<
>
>
|
|
|
>
>
|
>
>
>
>
|
<
>
>
|

>
|
|
>
|
>
>
>
>
>
>
>
>
|
|

|
>
|
1
2




3

4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
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
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108


109
110
111
112
113
114
115
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
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
191
192
193
194
195
196
197
198
199

200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
/***********************************************************************
 cpool.cpp - Implements the ConnectionPool class.






 Copyright (c) 2007-2009 by Educational Technology Resources, Inc. and
 (c) 2007 by Jonathan Wakely.  Others may also hold copyrights on
 code in this file.  See the CREDITS.txt file in the top directory
 of the distribution for details.

 This file is part of MySQL++.

 MySQL++ is free software; you can redistribute it and/or modify it
 under the terms of the GNU Lesser General Public License as published
 by the Free Software Foundation; either version 2.1 of the License, or
 (at your option) any later version.

 MySQL++ is distributed in the hope that it will be useful, but WITHOUT
 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
 License for more details.

 You should have received a copy of the GNU Lesser General Public
 License along with MySQL++; if not, write to the Free Software
 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
 USA
***********************************************************************/

#include "cpool.h"

#include "connection.h"

#include <algorithm>
#include <functional>

namespace mysqlpp {


/// \brief Functor to test whether a given ConnectionInfo object is
/// "too old".
///
/// \internal This is a template only because ConnectionInfo is private.
/// Making it a template means the private type is only used at the point
/// of instantiation, where it is accessible.

template <typename ConnInfoT>
class TooOld : std::unary_function<ConnInfoT, bool>
{
public:
#if !defined(DOXYGEN_IGNORE)
	TooOld(unsigned int tmax) :
	min_age_(time(0) - tmax)
	{
	}

	bool operator()(const ConnInfoT& conn_info) const
	{
		return !conn_info.in_use && conn_info.last_used <= min_age_;
	}

#endif
private:
	time_t min_age_;
};



//// clear /////////////////////////////////////////////////////////////
// Destroy connections in the pool, either all of them (completely
// draining the pool) or just those not currently in use.  The public
// method shrink() is an alias for clear(false).

void
ConnectionPool::clear(bool all)
{
	ScopedLock lock(mutex_);	// ensure we're not interfered with

	PoolIt it = pool_.begin();
	while (it != pool_.end()) {
		if (all || !it->in_use) {
			remove(it++);
		}
		else {
			++it;
		}
	}
}


//// exchange //////////////////////////////////////////////////////////
// Passed connection is defective, so remove it from the pool and return
// a new one.

Connection*
ConnectionPool::exchange(const Connection* pc)
{
	// Don't grab the mutex first.  remove() and grab() both do.
	// Inefficient, but we'd have to hoist their contents up into this
	// method or extract a mutex-free version of each mechanism for
	// each, both of which are also inefficient.
	remove(pc);
	return grab();
}


//// find_mru //////////////////////////////////////////////////////////
// Find most recently used available connection.  Uses operator< for
// ConnectionInfo to order pool with MRU connection last.  Returns 0 if
// there are no connections not in use.



Connection*
ConnectionPool::find_mru()
{
	PoolIt mru = std::max_element(pool_.begin(), pool_.end());
	if (mru != pool_.end() && !mru->in_use) {
		mru->in_use = true;
		return mru->conn;
	}
	else {
		return 0;
	}
}


//// grab //////////////////////////////////////////////////////////////

Connection*
ConnectionPool::grab()
{
	ScopedLock lock(mutex_);	// ensure we're not interfered with
	remove_old_connections();
	if (Connection* mru = find_mru()) {
		return mru;
	}
	else {
		// No free connections, so create and return a new one.
		pool_.push_back(ConnectionInfo(create()));
		return pool_.back().conn;
	}
}


//// release ///////////////////////////////////////////////////////////

void
ConnectionPool::release(const Connection* pc)
{
	ScopedLock lock(mutex_);	// ensure we're not interfered with

	for (PoolIt it = pool_.begin(); it != pool_.end(); ++it) {
		if (it->conn == pc) {
			it->in_use = false;
			it->last_used = time(0);
			break;
		}
	}
}


//// remove ////////////////////////////////////////////////////////////
// 2 versions:
//
// First takes a Connection pointer, finds it in the pool, and calls
// the second.  It's public, because Connection pointers are all
// outsiders see of the pool.
//
// Second takes an iterator into the pool, destroys the referenced
// connection and removes it from the pool.  This is only a utility
// function for use by other class internals.

void
ConnectionPool::remove(const Connection* pc)
{
	ScopedLock lock(mutex_);	// ensure we're not interfered with

	for (PoolIt it = pool_.begin(); it != pool_.end(); ++it) {
		if (it->conn == pc) {
			remove(it);
			return;
		}


	}
}

void
ConnectionPool::remove(const PoolIt& it)
{
	// Don't grab the mutex.  Only called from other functions that do
	// grab it.


	destroy(it->conn);
	pool_.erase(it);
}


//// remove_old_connections ////////////////////////////////////////////
// Remove connections that were last used too long ago.

void
ConnectionPool::remove_old_connections()
{
	TooOld<ConnectionInfo> too_old(max_idle_time());


	PoolIt it = pool_.begin();
	while ((it = std::find_if(it, pool_.end(), too_old)) != pool_.end()) {
		remove(it++);
	}
}


//// safe_grab /////////////////////////////////////////////////////////

Connection*
ConnectionPool::safe_grab()
{
	Connection* pc;
	while (!(pc = grab())->ping()) {
		remove(pc);
		pc = 0;
	}
	return pc;
}


} // end namespace mysqlpp

Changes to examples/tquery3.cpp.

1
2
3
4
5
6
7

8
9

10

11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
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










56




57































58
59
60
61
62

63

64
65
66
67

68
69
70


71

72
73

74

75
76
77
78



79



80









81

























82


83


















/***********************************************************************
 tquery3.cpp - Similar to tquery1.cpp but uses unquoted parameters.
	It's here more for code test coverage than because it shows
	something interesting.  We've historically had a problem with
	tqueries with just one parameter; we cover the quoted case in
	resetdb and the other tquery examples, so we get the unquoted
	one here.


 Copyright (c) 1998 by Kevin Atkinson, (c) 1999-2001 by MySQL AB, and

 (c) 2004-2009 by Educational Technology Resources, Inc.  Others may

 also hold copyrights on code in this file.  See the CREDITS.txt file
 in the top directory of the distribution for details.

 This file is part of MySQL++.

 MySQL++ is free software; you can redistribute it and/or modify it
 under the terms of the GNU Lesser General Public License as published
 by the Free Software Foundation; either version 2.1 of the License, or
 (at your option) any later version.

 MySQL++ is distributed in the hope that it will be useful, but WITHOUT
 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
 License for more details.

 You should have received a copy of the GNU Lesser General Public
 License along with MySQL++; if not, write to the Free Software
 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
 USA
***********************************************************************/




#include "cmdline.h"

#include "printdata.h"


#include <iostream>

using namespace std;





int






















main(int argc, char *argv[])

{



	// Get database access parameters from command line





	mysqlpp::examples::CommandLine cmdline(argc, argv);
	if (!cmdline) {
		return 1;
	}

























	try {











		// Establish the connection to the database server.
		mysqlpp::Connection con(mysqlpp::examples::db_name,
				cmdline.server(), cmdline.user(), cmdline.pass());

		// Build a template query to retrieve item names for stock
		// entries with a quantity over some threshold.
		mysqlpp::Query query = con.query(










				"select item from stock where num > %0");




		query.parse();
































		// Get a list of things we have lots of in stock
		if (mysqlpp::StoreQueryResult res = query.store(80)) {
			cout << "Stuff we have a lot of in stock:" << endl;
			for (size_t i = 0; i < res.num_rows(); ++i) {

				cout << '\t' << res[i]["item"] << endl;

			}
		}
		else {
			cerr << "Failed to get item list: " << query.error() << endl;

			return 1;
		}
	}


	catch (const mysqlpp::BadQuery& er) {

		// Handle any query errors
		cerr << "Query error: " << er.what() << endl;

		return 2;

	}
	catch (const mysqlpp::Exception& er) {
		// Catch-all for any other MySQL++ exceptions
		cerr << "Error: " << er.what() << endl;



		return 2;



	}



































	return 0;


}


















<
<
<
<
<
<
|
>

<
>
|
>
|
|



















>
>
>
|
>
|

>
|

|

>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>

>
>
>
|
>
>
>
>
>
|
|
|
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

<
>
>
>
>
>
>
>
>
>
>
>
|
|
<

<
<
|
>
>
>
>
>
>
>
>
>
>
|
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
|
|
|
<
>
|
>
|
<
|
<
>
|
<
<
>
>
|
>
|
<
>
|
>
|
<
<
|
>
>
>
|
>
>
>
|
>
>
>
>
>
>
>
>
>

>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>






1
2
3

4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
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
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107

108
109
110
111
112
113
114
115
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
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
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255






/// \file cpool.h
/// \brief Declares the ConnectionPool class.


/***********************************************************************
 Copyright (c) 2007-2008 by Educational Technology Resources, Inc. and
 (c) 2007 by Jonathan Wakely.  Others may also hold copyrights on
 code in this file.  See the CREDITS.txt file in the top directory
 of the distribution for details.

 This file is part of MySQL++.

 MySQL++ is free software; you can redistribute it and/or modify it
 under the terms of the GNU Lesser General Public License as published
 by the Free Software Foundation; either version 2.1 of the License, or
 (at your option) any later version.

 MySQL++ is distributed in the hope that it will be useful, but WITHOUT
 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
 License for more details.

 You should have received a copy of the GNU Lesser General Public
 License along with MySQL++; if not, write to the Free Software
 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
 USA
***********************************************************************/

#if !defined(MYSQLPP_CPOOL_H)
#define MYSQLPP_CPOOL_H

#include "beemutex.h"

#include <list>

#include <assert.h>
#include <time.h>

namespace mysqlpp {

#if !defined(DOXYGEN_IGNORE)
// Make Doxygen ignore this
class MYSQLPP_EXPORT Connection;
#endif

/// \brief Manages a pool of connections for programs that need more
/// than one Connection object at a time, but can't predict how many
/// they need in advance.
///
/// This class is useful in programs that need to make multiple
/// simultaneous queries on the database; this requires multiple
/// Connection objects due to a hard limitation of the underlying
/// C API.  Connection pools are most useful in multithreaded programs,
/// but it can be helpful to have one in a single-threaded program as
/// well.  Sometimes it's necessary to get more data from the server
/// while in the middle of processing data from an earlier query; this
/// requires multiple connections.  Whether you use a pool or manage
/// connections yourself is up to you, but realize that this class
/// takes care of a lot of subtle details for you that aren't obvious.
///
/// The pool's policy for connection reuse is to always return the 
/// \em most recently used connection that's not being used right now.
/// This ensures that excess connections don't hang around any longer
/// than they must.  If the pool were to return the \em least recently
/// used connection, it would be likely to result in a large pool of
/// sparsely used connections because we'd keep resetting the last-used 
/// time of whichever connection is least recently used at that moment.

class MYSQLPP_EXPORT ConnectionPool
{
public:
	/// \brief Create empty pool
	ConnectionPool() { }

	/// \brief Destroy object
	///
	/// If the pool raises an assertion on destruction, it means our
	/// subclass isn't calling clear() in its dtor as it should.
	virtual ~ConnectionPool() { assert(empty()); }

	/// \brief Returns true if pool is empty
	bool empty() const { return pool_.empty(); }

	/// \brief Return a defective connection to the pool and get a new
	/// one back.
	///
	/// Call this on receiving a BadQuery exception, with errnum()
	/// equal to CR_SERVER_GONE_ERROR.  It means the server was
	/// restarted or otherwise dropped your connection to it, so the
	/// Connection object is no longer usable.  You can avoid the
	/// need to use this by setting the ReconnectOption in your grab()
	/// override, but perhaps there are other reasons to need to
	/// exchange a bad connection for a good one.
	///
	/// This function wraps grab(), not safe_grab(), even though that
	/// could return another dead connection.  The assumption is that if
	/// your code is smart enough to detect one bad connection, it should
	/// be smart enough to detect a whole string of them.  Worst case,
	/// the whole pool is bad -- remote server went away -- and we have
	/// to empty the pool and start re-filling it.
	///
	/// \param pc pointer to a Connection object to be returned to the
	/// pool and marked as unused.
	///
	/// \retval a pointer to a different Connection object; not
	/// guaranteed to still be connected!
	virtual Connection* exchange(const Connection* pc);


	/// \brief Grab a free connection from the pool.
	///
	/// This method creates a new connection if an unused one doesn't
	/// exist, and destroys any that have remained unused for too long.
	/// If there is more than one free connection, we return the most
	/// recently used one; this allows older connections to die off over
	/// time when the caller's need for connections decreases.
	///
	/// Do not delete the returned pointer.  This object manages the
	/// lifetime of connection objects it creates.
	///
	/// \retval a pointer to the connection
	virtual Connection* grab();




	/// \brief Return a connection to the pool
	///
	/// Marks the connection as no longer in use.
	///
	/// The pool updates the last-used time of a connection only on
	/// release, on the assumption that it was used just prior.  There's
	/// nothing forcing you to do it this way: your code is free to
	/// delay releasing idle connections as long as it likes.  You
	/// want to avoid this because it will make the pool perform poorly;
	/// if it doesn't know approximately how long a connection has
	/// really been idle, it can't make good judgements about when to
	/// remove it from the pool.
	///
	/// \param pc pointer to a Connection object to be returned to the
	/// pool and marked as unused.
	virtual void release(const Connection* pc);

	/// \brief Removes the given connection from the pool
	///
	/// If you mean to simply return a connection to the pool after
	/// you're finished using it, call release() instead.  This method
	/// is primarily for error handling: you somehow have figured out
	/// that the connection is defective, so want it destroyed and
	/// removed from the pool.  If you also want a different connection
	/// to retry your operation on, call exchange() instead.
	///
	/// \param pc pointer to a Connection object to be removed from
	/// the pool and destroyed
	void remove(const Connection* pc);

	/// \brief Grab a free connection from the pool, testing that it's
	/// connected before returning it.
	///
	/// This is just a wrapper around grab(), Connection::ping() and
	/// release(), and is thus less efficient than grab().  Use it only
	/// when it's possible for MySQL server connections to go away
	/// unexpectedly, such as when the DB server can be restarted out
	/// from under your application.
	///
	/// \retval a pointer to the connection
	virtual Connection* safe_grab();

	/// \brief Remove all unused connections from the pool
	void shrink() { clear(false); }

protected:
	/// \brief Drains the pool, freeing all allocated memory.
	///
	/// A derived class must call this in its dtor to avoid leaking all
	/// Connection objects still in existence.  We can't do it up at
	/// this level because this class's dtor can't call our subclass's
	/// destroy() method.

	///
	/// \param all if true, remove all connections, even those in use
	void clear(bool all = true);


	/// \brief Create a new connection

	///
	/// Subclasses must override this.


	///
	/// Essentially, this method lets your code tell ConnectionPool
	/// what server to connect to, what login parameters to use, what
	/// connection options to enable, etc.  ConnectionPool can't know
	/// any of this without your help.

	///
	/// \retval A connected Connection object
	virtual Connection* create() = 0;



	/// \brief Destroy a connection
	///
	/// Subclasses must override this.
	///
	/// This is for destroying the objects returned by create().
	/// Because we can't know what the derived class did to create the
	/// connection we can't reliably know how to destroy it.
	virtual void destroy(Connection*) = 0;

	/// \brief Returns the maximum number of seconds a connection is
	/// able to remain idle before it is dropped.
	///
	/// Subclasses must override this as it encodes a policy issue,
	/// something that MySQL++ can't declare by fiat.
	///
	/// \retval number of seconds before an idle connection is destroyed
	/// due to lack of use
	virtual unsigned int max_idle_time() = 0;

	/// \brief Returns the current size of the internal connection pool.
	size_t size() const { return pool_.size(); }

private:
	//// Internal types
	struct ConnectionInfo {
		Connection* conn;
		time_t last_used;
		bool in_use;

		ConnectionInfo(Connection* c) :
		conn(c),
		last_used(time(0)),
		in_use(true)
		{
		}

		// Strict weak ordering for ConnectionInfo objects.
		// 
		// This ordering defines all in-use connections to be "less
		// than" those not in use.  Within each group, connections
		// less recently touched are less than those more recent.
		bool operator<(const ConnectionInfo& rhs) const
		{
			const ConnectionInfo& lhs = *this;
			return lhs.in_use == rhs.in_use ?
					lhs.last_used < rhs.last_used :
					lhs.in_use;
		}
	};
	typedef std::list<ConnectionInfo> PoolT;
	typedef PoolT::iterator PoolIt;

	//// Internal support functions
	Connection* find_mru();
	void remove(const PoolIt& it);
	void remove_old_connections();

	//// Internal data
	PoolT pool_;
	BeecryptMutex mutex_;
};

} // end namespace mysqlpp

#endif // !defined(MYSQLPP_CPOOL_H)

Changes to examples/tquery4.cpp.




1


2


3



4


5









6







7


8


9
10



11






12


13

14


15




16

17

18
19






20
21





22
23
24
25
26




27
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


56
57












58
59
60




61
62







63
64










65
66


67


68
69









70















71












72
73









74
75
76
77



78
79
80
81
82
83
84
85
86
87
88
89
90





91














92
93




94














/***********************************************************************


 tquery4.cpp - Tests other details about template queries, like unquoted


	parameters, multiple parameters, and preventing problems with LIKE



	patterns.  This exists more for code coverage than to demonstrate


	the library.

















 Copyright (c) 2009 by Martin Gallwey and (c) 2009 by Educational


 Technology Resources, Inc.  Others may also hold copyrights on code


 in this file.  See the CREDITS.txt file in the top directory of the
 distribution for details.










 This file is part of MySQL++.




 MySQL++ is free software; you can redistribute it and/or modify it


 under the terms of the GNU Lesser General Public License as published




 by the Free Software Foundation; either version 2.1 of the License, or

 (at your option) any later version.


 MySQL++ is distributed in the hope that it will be useful, but WITHOUT






 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public





 License for more details.

 You should have received a copy of the GNU Lesser General Public
 License along with MySQL++; if not, write to the Free Software
 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301




 USA
***********************************************************************/










#include "cmdline.h"


#include "printdata.h"



#include <iostream>












using namespace std;













int
main(int argc, char *argv[])



















{
	// Get database access parameters from command line
	mysqlpp::examples::CommandLine cmdline(argc, argv);
	if (!cmdline) {
		return 1;



	}





	try {

		// Establish the connection to the database server.
		mysqlpp::Connection con(mysqlpp::examples::db_name,
				cmdline.server(), cmdline.user(), cmdline.pass());












		// Modify an item using two named template query parameters
		mysqlpp::Query query = con.query("update stock "


				"set num = %0:quantity where num < %0:quantity");
		query.parse();




		query.template_defaults["quantity"] = 70;


		cout << "Query: " << query << endl;
		mysqlpp::SimpleResult result = query.execute();













		// Print the new table contents.
		print_stock_table(query);





		// Now let's check multiple dissimilar parameter types, and show







		// how to avoid conflicts between '%' as used in tqueries vs in
		// LIKE patterns.










		query.reset();
		query << "select * from stock where weight > %0q or "


				"description like '%%%1%%'";


		query.parse();
		cout << "\nQuery: " << query.str(1.2, "Mustard") << endl; 









		mysqlpp::StoreQueryResult res = query.store(1.2, "Mustard"); 




























		// Show what second tquery found
		print_stock_rows(res);









	}
	catch (const mysqlpp::BadQuery& er) {
		// Handle any query errors
		cerr << "Query error: " << er.what() << endl;



		return -1;
	}
	catch (const mysqlpp::BadConversion& er) {
		// Handle bad conversions
		cerr << "Conversion error: " << er.what() << endl <<
				"\tretrieved data size: " << er.retrieved <<
				", actual size: " << er.actual_size << endl;
		return -1;
	}
	catch (const mysqlpp::Exception& er) {
		// Catch-all for any other MySQL++ exceptions
		cerr << "Error: " << er.what() << endl;
		return -1;





	}















	return 0;




}











>
>
>
|
>
>
|
>
>
|
>
>
>
|
>
>
|
>
>
>
>
>
>
>
>
>

>
>
>
>
>
>
>
|
>
>
|
>
>
|
|
>
>
>

>
>
>
>
>
>
|
>
>

>
|
>
>
|
>
>
>
>
|
>
|
>

|
>
>
>
>
>
>
|
<
>
>
>
>
>
|

|
|
|
>
>
>
>
|
<
>
>
>

>
>
>
>
>
>
|
>
>
|

>
>
|
>
>
>
>
>

>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>

<
<
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
<
<
<
<
>
>
>
|
>
>
>
>

<
>
|
<
<
>
>
>
>
>
>
>
>
>
>

>
|
|
>
>
|
|
>
>
>
>
|
>
>
|
<
>
>
>
>
>
>
>
>
>
>
>
>

<
<
>
>
>
>

<
>
>
>
>
>
>
>
|
|
>
>
>
>
>
>
>
>
>
>
|
|
>
>
|
>
>
|
|
>
>
>
>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

>
>
>
>
>
>
>
>
>
>
>
>
|
<
>
>
>
>
>
>
>
>
>
|
<
<
<
>
>
>
|
|
<
<
<
<
<
<
|
|
|
|
|
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>

<
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
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
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78

79
80
81
82
83
84
85
86
87
88
89
90
91
92
93

94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
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
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
191
192
193
194

195
196
197
198
199
200
201
202
203
204
205
206
207


208
209
210
211
212

213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
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
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
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
336
<?xml version="1.0" encoding='UTF-8'?>
<!DOCTYPE sect1 PUBLIC "-//OASIS//DTD DocBook V4.2//EN"
    "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">

<sect1 id="threads">
  <title>Using MySQL++ in a Multithreaded Program</title>

  <para>MySQL++ is not &#x201C;thread safe&#x201D; in any
  meaningful sense. MySQL++ contains very little code that
  actively prevents trouble with threads, and all of it is
  optional. We have done some work in MySQL++ to make thread
  safety <emphasis>achievable</emphasis>, but it doesn&#x2019;t come
  for free.</para>

  <para>The main reason for this is that MySQL++ is
  generally I/O-bound, not processor-bound. That is, if
  your program&#x2019;s bottleneck is MySQL++, the ultimate
  cause is usually the I/O overhead of using a client-server
  database. Doubling the number of threads will just let your
  program get back to waiting for I/O twice as fast. Since <ulink
  url="http://www.eecs.berkeley.edu/Pubs/TechRpts/2006/EECS-2006-1.pdf">threads
  are evil</ulink> and generally can&#x2019;t help MySQL++, the only
  optional thread awareness features we turn on in the shipping
  version of MySQL++ are those few that have no practical negative
  consequences. Everything else is up to you, the programmer, to
  evaluate and enable as and when you need it.</para>

  <para>We&#x2019;re going to assume that you are reading this chapter
  because you find yourself needing to use threads for some other
  reason than to speed up MySQL access. Our purpose here is limited
  to setting down the rules for avoiding problems with MySQL++ in a
  multi-threaded program. We won&#x2019;t go into the broader issues of
  thread safety outside the scope of MySQL++. You will need a grounding
  in threads in general to get the full value of this advice.</para>

  <sect2 id="thread-build">
    <title>Build Issues</title>

    <para>Before you can safely use MySQL++ with threads, there are
    several things you must do to get a thread-aware build:</para>

    <orderedlist>
      <listitem>
        <para><emphasis>Build MySQL++ itself with thread awareness
        turned on.</emphasis></para>

        <para>On Linux, Cygwin and Unix (OS X, *BSD, Solaris...),
        pass the <computeroutput>--enable-thread-check</computeroutput>
        flag to the <filename>configure</filename> script. Beware, this
        is only a request to the <filename>configure</filename> script
        to look for thread support on your system, not a requirement
        to do or die: if the script doesn&#x2019;t find what it needs
        to do threading, MySQL++ will just get built without thread
        support. See <filename>README-Unix.txt</filename> for more
        details.</para>

        <para>On Windows, if you use the Visual C++ project files or
        the MinGW Makefile that comes with the MySQL++ distribution,
        threading is always turned on, due to the nature of
        Windows.</para>

        <para>If you build MySQL++ in some other way, such as with
        Dev-Cpp (based on MinGW) you&#x2019;re on your own to enable
        thread awareness.</para>
      </listitem>

      <listitem>
        <para><emphasis>Link your program to a thread-aware build of the
        MySQL C API library.</emphasis></para>

        <para>If you use a binary distribution of MySQL on Unixy
        systems, you usually get two different versions of the MySQL
        C API library, one with thread support and one without. These
        are typically called <filename>libmysqlclient</filename> and
        <filename>libmysqlclient_r</filename>, the latter being the
        thread-safe one. (The &#x201C;<filename>_r</filename>&#x201D;
        means reentrant.)</para>


        <para>If you&#x2019;re using the Windows binary distribution
        of MySQL, you should have only one version of the C
        API library, which should be thread-aware. If you have
        two, you probably just have separate debug and optimized
        builds. See <filename>README-Visual-C++.txt</filename> or
        <filename>README-MinGW.txt</filename> for details.</para>

        <para>If you build MySQL from source, you might only get
        one version of the MySQL C API library, and it can have
        thread awareness or not, depending on your configuration
        choices. This is the case with Cygwin, where you currently
        have no choice but to build the C API library from source. (See
        <filename>README-Cygwin.txt</filename>.)</para>
      </listitem>


      <listitem>
        <para><emphasis>Enable threading in your program&#x2019;s build
        options.</emphasis></para>

        <para>This is different for every platform, but it&#x2019;s
        usually the case that you don&#x2019;t get thread-aware builds
        by default. Depending on the platform, you might need to change
        compiler options, linker options, or both. See your development
        environment&#x2019;s documentation, or study how MySQL++ itself
        turns on thread-aware build options when requested.</para>
      </listitem>
    </orderedlist>
  </sect2>


  <sect2 id="thread-conn-mgmt">
    <title>Connection Management</title>

    <para>The MySQL C API underpinning MySQL++ does not allow multiple
    concurrent queries on a single connection. You can run into this
    problem in a single-threaded program, too, which is why we cover the
    details elsewhere, in <xref linkend="concurrentqueries"/>.
    It&#x2019;s a thornier problem when using threads, though.</para>

    <para>The simple fix is to just create a separarate <ulink
    url="Connection" type="classref"/> object for each thread that
    needs to make database queries. This works well if you have a small
    number of threads that need to make queries, and each thread uses
    its connection often enough that the server doesn&#x2019;t <link
    linkend="conn-timeout">time out</link> waiting for queries.</para>

    <para>If you have lots of threads or the frequency of queries is
    low, the connection management overhead will be excessive. To avoid
    that, we created the <ulink url="ConnectionPool" type="classref"/>
    class. It manages a pool of <classname>Connection</classname>
    objects like library books: a thread checks one out, uses
    it, and then returns it to the pool as soon as it&#x2019;s
    done with it. This keeps the number of active connections
    low. We suggest that you keep each connection&#x2019;s
    use limited to a single variable scope for <ulink
    url="http://en.wikipedia.org/wiki/RAII">RAII</ulink> reasons;
    we created a little helper called <ulink url="ScopedConnection"
    type="classref"/> to make that easy.</para>



    <para><classname>ConnectionPool</classname> has three
    methods that you need to override in a subclass to
    make it concrete: <methodname>create()</methodname>,
    <methodname>destroy()</methodname>, and
    <methodname>max_idle_time()</methodname>. These overrides let
    the base class delegate operations it can&#x2019;t successfully do
    itself to its subclass. The <classname>ConnectionPool</classname>
    can&#x2019;t know how to <methodname>create()</methodname>
    the <classname>Connection</classname> objects, because that
    depends on how your program gets login parameters, server
    information, etc.  <classname>ConnectionPool</classname>
    also makes the subclass <methodname>destroy()</methodname>
    the <classname>Connection</classname> objects it created; it
    could assume that they&#x2019;re simply allocated on the heap
    with <methodname>new</methodname>, but it can&#x2019;t be sure,
    so the base class delegates destruction, too. Finally, the base
    class can&#x2019;t know which connection idle timeout policy
    would make the most sense to the client, so it asks its subclass
    via the <methodname>max_idle_time()</methodname> method.</para>





    <para><classname>ConnectionPool</classname> also allows you to
    override <methodname>release()</methodname>, if needed. For simple
    uses, it&#x2019;s not necessary to override this.</para>

    <para>In designing your <classname>ConnectionPool</classname>
    derivative, you might consider making it a <ulink
    url="http://en.wikipedia.org/wiki/Singleton_pattern">Singleton</ulink>,
    since there should only be one pool in a program.</para>


    <para>Another thing you might consider doing is passing a
    <ulink url="ReconnectOption" type="classref"/> object to


    <methodname>Connection::set_option()</methodname> in your
    <methodname>create()</methodname> override before returning the
    new <classname>Connection</classname> pointer. This will cause
    the underlying MySQL C API to try to reconnect to the database
    server if a query fails because the connection was dropped
    by the server. This can happen if the DB server is allowed to
    restart out from under your application. In many applications,
    this isn&#x2019;t allowed, or if it does happen, you might want
    your code to be able to detect it, so MySQL++ doesn&#x2019;t set
    this option for you automatically.</para>

    <para>Here is an example showing how to use connection pools with
    threads:</para>

    <programlisting><xi:include href="cpool.txt" parse="text"
    xmlns:xi="http://www.w3.org/2001/XInclude"/></programlisting>

    <para>The example works with both Windows native
    threads and with POSIX threads.<footnote><para>The file
    <filename>examples/threads.h</filename> contains a few macros and
    such to abstract away the differences between the two threading
    models.</para></footnote> Because thread-enabled builds are only
    the default on Windows, it&#x2019;s quite possible for this program
    to do nothing on other platforms. See above for instructions on
    enabling a thread-aware build.</para>


    <para>If you write your code without checks for thread support
    like you see in the code above and link it to a build of MySQL++
    that isn&#x2019;t thread-aware, it will still try to run. The
    threading mechanisms fall back to a single-threaded mode when
    threads aren&#x2019;t available. A particular danger is that the
    mutex lock mechanism used to keep the pool&#x2019;s internal data
    consistent while multiple threads access it will just quietly
    become a no-op if MySQL++ is built without thread support. We do
    it this way because we don&#x2019;t want to make thread support
    a MySQL++ prerequisite. And, although it would be of limited
    value, this lets you use <classname>ConnectionPool</classname>
    in single-threaded programs.</para>



    <para>You might wonder why we don&#x2019;t just work around
    this weakness in the C API transparently in MySQL++ instead of
    suggesting design guidelines to avoid it. We&#x2019;d like to do
    just that, but how?</para>


    <para>If you consider just the threaded case, you could argue for
    the use of mutexes to protect a connection from trying to execute
    two queries at once. The cure is worse than the disease: it turns a
    design error into a performance sap, as the second thread is blocked
    indefinitely waiting for the connection to free up. Much better to
    let the program get the &#x201C;Commands out of sync&#x201D; error,
    which will guide you to this section of the manual, which tells you
    how to avoid the error with a better design.</para>

    <para>Another option would be to bury
    <classname>ConnectionPool</classname> functionality within MySQL++
    itself, so the library could create new connections at need.
    That&#x2019;s no good because the above example is the most complex
    in MySQL++, so if it were mandatory to use connection pools, the
    whole library would be that much more complex to use. The whole
    point of MySQL++ is to make using the database easier. MySQL++
    offers the connection pool mechanism for those that really need it,
    but an option it must remain.</para>
  </sect2>


  <sect2 id="thread-helpers">
    <title>Helper Functions</title>

    <para><classname>Connection</classname> has several thread-related
    static methods you might care about when using MySQL++ with
    threads.</para>

    <para>You can call
    <methodname>Connection::thread_aware()</methodname> to
    determine whether MySQL++ and the underlying C API library were
    both built to be thread-aware. I want to stress that thread
    <emphasis>awareness</emphasis> is not the same thing as thread
    <emphasis>safety</emphasis>: it&#x2019;s still up to you to make
    your code thread-safe. If this method returns true, it just means
    it&#x2019;s <emphasis>possible</emphasis> to achieve thread-safety,
    not that you actually have it.</para>

    <para>If your program&#x2019;s connection-management strategy
    allows a thread to use a <classname>Connection</classname>
    object that another thread created, you need to know
    about <methodname>Connection::thread_start()</methodname>.
    This function sets up per-thread resources needed to make MySQL
    server calls. You don&#x2019;t need to call it when you use the
    simple <classname>Connection</classname>-per-thread strategy,
    because this function is implicitly called the first time you
    create a <classname>Connection</classname> in a thread. It&#x2019;s
    not harmful to call this function from a thread that previously
    created a <classname>Connection</classname>, just unnecessary. The
    only time it&#x2019;s necessary is when a thread can make calls
    to the database server on a <classname>Connection</classname>
    that another thread created and that thread hasn&#x2019;t already
    created a <classname>Connection</classname> itself.</para>

    <para>If you use <classname>ConnectionPool</classname>, you should
    call <methodname>thread_start()</methodname> at the start of each
    worker thread because you probably can&#x2019;t reliably predict
    whether your <methodname>grab()</methodname> call will create a new
    <classname>Connection</classname> or will return one previously
    returned to the pool from another thread.  It&#x2019;s possible
    to conceive of situations where you can guarantee that each pool
    user always creates a fresh <classname>Connection</classname> the
    first time it calls <methodname>grab()</methodname>, but thread
    programming is complex enough that it&#x2019;s best to take the
    safe path and always call <methodname>thread_start()</methodname>
    early in each worker thread.</para>


    <para>Finally, there&#x2019;s the complementary method,
    <methodname>Connection::thread_end()</methodname>. Strictly
    speaking, it&#x2019;s not <emphasis>necessary</emphasis> to call
    this. The per-thread memory allocated by the C API is small,
    it doesn&#x2019;t grow over time, and a typical thread is going
    to need this memory for its entire run time. Memory debuggers
    aren&#x2019;t smart enough to know all this, though, so they will
    gripe about a memory leak unless you call this from each thread
    that uses MySQL++ before that thread exits.</para>




    <para>Although its name suggests otherwise,
    <methodname>Connection::thread_id()</methodname> has nothing to
    do with anything in this chapter.</para>
  </sect2>








  <sect2 id="thread-data-sharing">
    <title>Sharing MySQL++ Data Structures</title>

    <para>We&#x2019;re in the process of making it safer to share
    MySQL++&#x2019;s data structures across threads. Although things
    are getting better, it&#x2019;s highly doubtful that all problems
    with this are now fixed. By way of illustration, allow me explain
    one aspect of this problem and how we solved it in MySQL++
    3.0.0.</para>

    <para>When you issue a database query that returns rows, you
    also get information about the columns in each row. Since the
    column information is the same for each row in the result set,
    older versions of MySQL++ kept this information in the result
    set object, and each <ulink url="Row" type="classref"/> kept
    a pointer back to the result set object that created it so it
    could access this common data at need. This was fine as long as
    each result set object outlived the <classname>Row</classname>
    objects it returned.  It required uncommon usage patterns to run
    into trouble in this area in a single-threaded program, but in
    a multi-threaded program it was easy. For example, there&#x2019;s
    frequently a desire to let one connection do the queries, and other
    threads process the results.  You can see how avoiding lifetime
    problems here would require a careful locking strategy.</para>


    <para>We got around this in MySQL++ v3.0 by giving these shared data
    structures a lifetime independent of the result set object that
    intitially creates it. These shared data structures stick around
    until the last object needing them gets destroyed.</para>

    <para>Although this is now a solved problem, I bring it up because
    there are likely other similar lifetime and sequencing problems
    waiting to be discovered inside MySQL++. If you would like to
    help us find these, by all means, share data between threads
    willy-nilly.  We welcome your crash reports on the MySQL++
    mailing list. But if you&#x2019;d prefer to avoid problems,
    it&#x2019;s better to keep all data about a query within a single
    thread. Between this and the advice in prior sections, you should
    be able to use threads with MySQL++ without trouble.</para>
  </sect2>
</sect1>

Changes to examples/transaction.cpp.

1
2
3

4
5

6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27

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

56


57
58
59
60
61
62
63
64
65
66
67
68

69



70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85


86







87

88
89
90
91



92
93
94
95
96
97


98


99
100
101
102
103

104
105
106
107
108
109




110
111
112
113
114
115
116

117
118

119
/***********************************************************************
 transaction.cpp - Example showing how to use MySQL++'s transaction
 	features.


 Copyright (c) 1998 by Kevin Atkinson, (c) 1999-2001 by MySQL AB, and

 (c) 2004-2009 by Educational Technology Resources, Inc.  Others may
 also hold copyrights on code in this file.  See the CREDITS.txt file
 in the top directory of the distribution for details.

 This file is part of MySQL++.

 MySQL++ is free software; you can redistribute it and/or modify it
 under the terms of the GNU Lesser General Public License as published
 by the Free Software Foundation; either version 2.1 of the License, or
 (at your option) any later version.

 MySQL++ is distributed in the hope that it will be useful, but WITHOUT
 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
 License for more details.

 You should have received a copy of the GNU Lesser General Public
 License along with MySQL++; if not, write to the Free Software
 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
 USA
***********************************************************************/


#include "cmdline.h"
#include "printdata.h"
#include "stock.h"

#include <iostream>
#include <cstdio>

using namespace std;




int
main(int argc, char *argv[])
{
	// Get database access parameters from command line
	mysqlpp::examples::CommandLine cmdline(argc, argv);
	if (!cmdline) {
		return 1;


	}



	try {
		// Establish the connection to the database server.
		mysqlpp::Connection con(mysqlpp::examples::db_name,
				cmdline.server(), cmdline.user(), cmdline.pass());

		// Show initial state
		mysqlpp::Query query = con.query();
		cout << "Initial state of stock table:" << endl;
		print_stock_table(query);



		// Insert a few rows in a single transaction set


		{
			// Use a higher level of transaction isolation than MySQL
			// offers by default.  This trades some speed for more
			// predictable behavior.  We've set it to affect all
			// transactions started through this DB server connection,
			// so it affects the next block, too, even if we don't
			// commit this one.
			mysqlpp::Transaction trans(con,
					mysqlpp::Transaction::serializable,
					mysqlpp::Transaction::session);

			stock row("Sauerkraut", 42, 1.2, 0.75,

					mysqlpp::sql_date("2006-03-06"), mysqlpp::null);



			query.insert(row);
			query.execute();

			cout << "\nRow inserted, but not committed." << endl;
			cout << "Verify this with another program (e.g. simple1), "
					"then hit Enter." << endl;
			getchar();

			cout << "\nCommitting transaction gives us:" << endl;
			trans.commit();
			print_stock_table(query);
		}
			
		// Now let's test auto-rollback
		{
			// Start a new transaction, keeping the same isolation level


			// we set above, since it was set to affect the session.







			mysqlpp::Transaction trans(con);

			cout << "\nNow adding catsup to the database..." << endl;

			stock row("Catsup", 3, 3.9, 2.99,
					mysqlpp::sql_date("2006-03-06"), mysqlpp::null);



			query.insert(row);
			query.execute();
		}
		cout << "\nNo, yuck! We don't like catsup. Rolling it back:" <<
				endl;
		print_stock_table(query);


			


	}
	catch (const mysqlpp::BadQuery& er) {
		// Handle any query errors
		cerr << "Query error: " << er.what() << endl;
		return -1;

	}
	catch (const mysqlpp::BadConversion& er) {	
		// Handle bad conversions
		cerr << "Conversion error: " << er.what() << endl <<
				"\tretrieved data size: " << er.retrieved <<
				", actual size: " << er.actual_size << endl;




		return -1;
	}
	catch (const mysqlpp::Exception& er) {
		// Catch-all for any other MySQL++ exceptions
		cerr << "Error: " << er.what() << endl;
		return -1;
	}


	return 0;

}
<
<
|
>

<
>
|
|
|



















>
|
|
|

<
|

|

>
>
>
|
<
|
<
<
|
<
>
>
|
>
>
|
<
|
|
<
|
<
|
|
<
>

>
|
>
>
|
<
<
|
|
|
|
|
|
|
|
<
>
|
>
>
>
|
<
|
<
<
<
<
|
<
<
<
|
|
|
<
<
>
>
|
>
>
>
>
>
>
>
|
>
|
|
<
|
>
>
>
|
<
<
<
<
<
>
>
|
>
>
|
<
|
<
<
>
|
|
|
<
<
|
>
>
>
>
|
|
|
<
<
<
|
>

<
>
|


1
2
3

4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
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
56
57
58
59


60
61
62
63
64
65
66
67

68
69
70
71
72
73

74




75



76
77
78


79
80
81
82
83
84
85
86
87
88
89
90
91
92

93
94
95
96
97





98
99
100
101
102
103

104


105
106
107
108


109
110
111
112
113
114
115
116



117
118
119

120
121


/// \file sqlstream.h
/// \brief Defines a class for building quoted and escaped SQL text.


/***********************************************************************
 Copyright (c) 2008 by AboveNet, Inc.  Others may also hold copyrights
 on code in this file.  See the CREDITS file in the top directory of
 the distribution for details.

 This file is part of MySQL++.

 MySQL++ is free software; you can redistribute it and/or modify it
 under the terms of the GNU Lesser General Public License as published
 by the Free Software Foundation; either version 2.1 of the License, or
 (at your option) any later version.

 MySQL++ is distributed in the hope that it will be useful, but WITHOUT
 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
 License for more details.

 You should have received a copy of the GNU Lesser General Public
 License along with MySQL++; if not, write to the Free Software
 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
 USA
***********************************************************************/

#if !defined(MYSQLPP_SQLSTREAM_H)
#define MYSQLPP_SQLSTREAM_H

#include "common.h"


#include <sstream>

namespace mysqlpp {

#if !defined(DOXYGEN_IGNORE)
// Make Doxygen ignore this
class MYSQLPP_EXPORT Connection;
#endif




/// \brief A class for building SQL-formatted strings.

///
/// See the user manual for more details about these options.

class MYSQLPP_EXPORT SQLStream :
public std::ostringstream
{

public:
	/// \brief Create a new stream object attached to a connection.

	///

	/// \param c connection used for escaping text
	/// \param pstr an optional initial string

	SQLStream(Connection* c, const char* pstr = 0);

	/// \brief Create a new stream object as a copy of another.
	///
	/// This is a traditional copy ctor.
	SQLStream(const SQLStream& s);



	/// \brief Return a SQL-escaped version of a character buffer
	///
	/// \param ps pointer to C++ string to hold escaped version; if
	/// original is 0, also holds the original data to be escaped
	/// \param original if given, pointer to the character buffer to
	/// escape instead of contents of *ps
	/// \param length if both this and original are given, number of
	/// characters to escape instead of ps->length()

	///
	/// \retval number of characters placed in *ps
	///
	/// \see comments for escape_string(char*, const char*, size_t)
	/// and DBDriver::escape_string(std::string*, const char *, size_t)
	/// for further details.

	size_t escape_string(std::string* ps, const char* original = 0,




			size_t length = 0) const;




	/// \brief Return a SQL-escaped version of the given character
	/// buffer


	///
	/// \param escaped character buffer to hold escaped version; must
	/// point to at least (length * 2 + 1) bytes
	/// \param original pointer to the character buffer to escape
	/// \param length number of characters to escape
	///
	/// \retval number of characters placed in escaped
	///
	/// DBDriver provides two versions of this method and 
	/// Query::escape_string() calls the appropriate one based on whether
	/// or not a database connection is available.  If the connection
	/// is available, it can call the DBDriver::escape_string() method.
	/// If there is no database connection available (normally only in
	/// testing), then DBDriver provides a static version of the function 

	/// that doesn't use a database connection.
	///
	/// \see comments for DBDriver::escape_string(char*, const char*, size_t),
	/// DBDriver::escape_string_no_conn(char*, const char*, size_t)
	/// for further details.





	size_t escape_string(char* escaped, const char* original,
			size_t length) const;

	/// \brief Assigns contents of another SQLStream to this one
	SQLStream& operator=(const SQLStream& rhs);


	/// \brief Connection to send queries through


	Connection* conn_;
};




/// \brief Insert raw string into the given stream.
///
/// This is just syntactic sugar for SQLStream::str(void)
inline std::ostream& operator <<(std::ostream& os, SQLStream& s)
{
	return os << s.str();
}





} // end namespace mysqlpp


#endif // !defined(MYSQLPP_SQLSTREAM_H)

Changes to examples/vstudio/mfc/mfc.cpp.


1

2




3


























































































































































4

5





6


7





















































































































































8

9

































































































































































10



11





12


13




14














































































































































































































































































































15

16

17
18

19























































































































































































































































































































20
21

22




23


24



25





















































































































































26






27





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

























































































































/***********************************************************************

 mfc.cpp - Skeletal main module of the MySQL++ MFC example program.




	Nothing interesting to see here.  Move along to mfc_dlg.cpp, folks.




























































































































































 Copyright (c) 2007 by Educational Technology Resources, Inc.  Others 





 may also hold copyrights on code in this file.  See the CREDITS.txt


 file in the top directory of the distribution for details.























































































































































 This file is part of MySQL++.





































































































































































 MySQL++ is free software; you can redistribute it and/or modify it





 under the terms of the GNU Lesser General Public License as published


 by the Free Software Foundation; either version 2.1 of the License, or




 (at your option) any later version.
















































































































































































































































































































 MySQL++ is distributed in the hope that it will be useful, but WITHOUT

 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public

 License for more details.
























































































































































































































































































































 You should have received a copy of the GNU Lesser General Public

 License along with MySQL++; if not, write to the Free Software




 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301


 USA



***********************************************************************/




























































































































































#include "stdafx.h"





#include "mfc.h"





#include "mfc_dlg.h"
















































































































































CApp gApplication;

































































































































































BOOL CApp::InitInstance()

























































































































































{


	// Set up Windows commomn controls


	INITCOMMONCONTROLSEX InitCtrls;



	InitCtrls.dwSize = sizeof(InitCtrls);
	InitCtrls.dwICC = ICC_WIN95_CLASSES;

	InitCommonControlsEx(&InitCtrls);























































































































































	CWinApp::InitInstance();






















































































































































































































































































































































	// Initialize Winsock for MySQL communication, start GUI








	if (AfxSocketInit()) {

		CExampleDlg dlg;
































		m_pMainWnd = &dlg;

		dlg.DoModal();


























































































	}

	else {









		AfxMessageBox(IDP_SOCKETS_INIT_FAILED);

	}













	return FALSE;












}
























































































































>
|
>
|
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

>
|
>
>
>
>
>
|
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

>
>
>
|
>
>
>
>
>
|
>
>
|
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

>
|
>
|
|
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

|
>
|
>
>
>
>
|
>
>
|
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

>
>
>
>
>
>
|
>
>
>
>
>
|
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
>
|
>
>
|
>
>
>
|
|
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

>
|
>
>
>
>
>
>
>
>
|
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
|
>
>
>
>
>
>
>
>
>
|
>
|
>
>
>
>
>
>
>
>
>
>
>

>
|
>
>
>
>
>
>
>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
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
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
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
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
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
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
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
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
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
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
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
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
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
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
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
1694
1695
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
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
1883
1884
1885
1886
1887
1888
1889
1890
1891
1892
1893
1894
1895
1896
1897
1898
1899
1900
1901
1902
1903
1904
1905
1906
1907
1908
1909
1910
1911
1912
1913
1914
1915
1916
1917
1918
1919
1920
1921
1922
1923
1924
1925
1926
1927
1928
1929
1930
1931
1932
1933
1934
1935
1936
1937
1938
1939
1940
1941
1942
1943
1944
1945
1946
1947
1948
1949
1950
1951
1952
1953
1954
1955
1956
1957
1958
1959
1960
1961
1962
1963
1964
1965
1966
1967
1968
1969
1970
1971
1972
1973
1974
1975
1976
1977
1978
1979
1980
1981
1982
1983
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993
1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
2027
2028
2029
2030
2031
2032
2033
2034
2035
2036
2037
2038
2039
2040
2041
2042
2043
2044
2045
2046
2047
2048
2049
2050
2051
2052
2053
2054
2055
2056
2057
2058
2059
2060
2061
2062
2063
2064
2065
2066
2067
2068
2069
2070
2071
2072
2073
2074
2075
2076
2077
2078
2079
2080
2081
2082
2083
2084
2085
2086
2087
2088
2089
2090
2091
2092
2093
2094
2095
2096
2097
2098
2099
2100
2101
2102
2103
2104
2105
2106
2107
2108
2109
2110
2111
2112
2113
2114
2115
2116
2117
2118
2119
2120
2121
2122
2123
2124
2125
2126
2127
2128
2129
2130
2131
2132
2133
2134
2135
2136
2137
2138
2139
2140
2141
2142
2143
2144
2145
2146
2147
2148
2149
2150
2151
2152
2153
2154
2155
2156
2157
2158
2159
2160
2161
2162
2163
2164
2165
2166
2167
2168
2169
2170
2171
2172
2173
2174
2175
2176
2177
2178
2179
2180
2181
2182
2183
2184
2185
2186
2187
2188
2189
2190
2191
2192
2193
2194
2195
2196
2197
2198
2199
2200
2201
2202
2203
2204
2205
2206
2207
2208
2209
2210
2211
2212
2213
2214
2215
2216
2217
2218
2219
2220
2221
2222
2223
2224
2225
2226
2227
2228
2229
2230
2231
2232
2233
2234
2235
2236
2237
2238
2239
2240
2241
2242
2243
2244
2245
2246
2247
2248
2249
2250
2251
2252
2253
2254
2255
2256
2257
2258
2259
2260
2261
2262
2263
2264
2265
2266
2267
2268
2269
2270
2271
2272
2273
2274
2275
2276
2277
2278
2279
2280
2281
2282
2283
2284
2285
2286
2287
2288
2289
2290
2291
2292
2293
2294
2295
2296
2297
2298
2299
2300
2301
2302
2303
2304
2305
2306
2307
2308
2309
2310
2311
2312
2313
2314
2315
2316
2317
2318
2319
2320
2321
2322
2323
2324
2325
2326
2327
2328
2329
2330
2331
2332
2333
2334
2335
2336
2337
2338
2339
2340
2341
2342
2343
2344
2345
2346
2347
2348
2349
2350
2351
2352
2353
2354
2355
2356
2357
2358
2359
2360
2361
2362
2363
2364
2365
2366
2367
2368
2369
2370
2371
2372
2373
2374
2375
2376
2377
2378
2379
2380
2381
2382
2383
2384
2385
2386
2387
2388
2389
2390
2391
2392
2393
2394
2395
2396
2397
2398
2399
2400
2401
2402
2403
2404
2405
2406
2407
2408
2409
2410
2411
2412
2413
2414
2415
2416
2417
2418
2419
2420
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
2475
2476
2477
2478
2479
2480
2481
2482
2483
2484
2485
2486
2487
2488
2489
2490
2491
2492
2493
2494
2495
2496
2497
2498
2499
2500
2501
2502
2503
2504
2505
2506
2507
2508
2509
2510
2511
2512
2513
2514
2515
2516
2517
2518
2519
2520
2521
2522
2523
2524
2525
2526
2527
2528
2529
2530
2531
2532
2533
2534
2535
2536
2537
2538
2539
2540
2541
2542
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
3.0.0, 2008.02.29 (r2236) The "Giant Leap Forward" release

    THIS IS NOT A DROP-IN REPLACEMENT FOR MySQL++ v2.x!

    You will have to recompile your program against this version
    of the library, and you will almost certainly have to make code
    changes as well.  Please see these sections in the user manual
    for information on migrating your code to this new version:

    http://tangentsoft.net/mysql++/doc/html/userman/breakages.html#api-3.0.0
    http://tangentsoft.net/mysql++/doc/html/userman/breakages.html#abi-3.0.0

    o Added ConnectionPool class, primarily to let multithreaded
      programs share a set of Connection objects safely in situations
      where it isn't acceptable to have a Connection per thread.

    o Created examples/cpool.cpp to demonstrate this new class.

    o Added RefCountedPointer template, which provides automatic
      memory management and data sharing.  It's not intended
      for use outside of MySQL++ itself, but it's the mechanism
      behind everything below where reference counting is mentioned.
      I created the initial version of it, but Jonathan Wakely almost
      completely rebuilt it, and Joseph Artsimovich provided helpful
      commentary and advice as well.

    o Many improvements to Specialized SQL Structures (SSQLS):

      - Renamed custom* to ssqls*.  There's still a custom.h which
        #includes ssqls.h for you, but it's only intended to ease
        the transition to the new name.  It will go away in a future
        release, probably as soon as v3.1.

      - SSQLSes are finally compatible with Null<>-wrapped types.  This
        feature is based loosely on the "Waba" patch posted to the
        mailing list back in the v2.0 days, but extended to allow
        Null<T> types for key fields.  (The Waba patch only allowed
        these types in non-key fields.)

      - It's no longer necessary to define a different SSQLS for each
        different field set you use in queries.  That is to say,
        you can define an SSQLS for an entire table and store just a
        subset of the table in it now, with the other fields keeping
        default values.  Removed examples/custom6.cpp, as custom1.cpp
        can now demonstrate the same thing, implicitly.

      - An SSQLS's field order no longer has to match the order of
        fields in the result set it is populated from.

      - As a result of previous, removed sql_create_c_order_* macros;
        they have no purpose now.

      - Removed order parameters from sql_create_complete_*, which now
        gives it the same functionality as sql_create_c_names_* so
        removed the latter, too.

      - Removed "basic" variants of SSQLS creation macros.  They've
        been unofficially deprecated by dint of being all but
        undocumented and unexemplified for a very long time now.

      - It's now possible to use mysqlpp::String, Date, DateTime, and
        Time types in the key field positions in an SSQLS as they
        now support the necessary comparison interfaces.

      - If you use a floating-point data type in one of the key field
        positions, it no longer uses exact comparison logic.  Instead,
        it now does [in]equality comparisons by testing whether the
        difference between two floating-point values is less than a
        configurable threshold defaulting to 0.00001.
    
      - You can now use 'bool' type in an SSQLS.

      - Renamed _table static member variable in each SSQLS to table_
        and made it private.  There are now public setter and getter
        methods, table().

      - Added per-instance table name overriding via instance_table()
        setter.  table() getter returns static version if this is not
        set, so it's still a global setting by default.

    o You can now use mysqlpp::null as a template query parameter to
      get a SQL null.

    o Replaced template ColData_Tmpl<T>:

      - Used to have typedef ColData_Tmpl<std::string> MutableColData.
        It was used only once within MySQL++ itself, and was never
        documented as a class for end users.  This one use within
        the library was a crock, so we just replaced this use with
        std::string and removed the typedef.

      - This left just one use of ColData_Tmpl<T>, instantiating it
        with the MySQL++ utility class const_string, basically a
        clone of std::string with all the mutating features removed.
        Folded the functionality of const_string into the template,
        renamed the result to String, and deleted the const_string
        class.  It'd be a complete std::string replacement -- with
        SQL-related enhancements -- if it were modifiable, but MySQL++
        doesn't need it to be modifiable.  Yet, it's still the closest
        thing MySQL++ has to its own string type; thus the name.

      - Replaced its internal buffer management with a much more
        clever reference counted scheme.  This shows its greatest
        advantage in the return from Row::operator[](), which for
        technical reasons must return by value, not by reference
        as is more common.  This lets you pass around Strings by
        value while having the efficiency of reference semantics.
        This can be important with large return values, like BLOBs.

      - Converting String to numeric types (ints, floats...) uses a
        new, cleaner system by Jonathan Wakely.  Unless you were
        abusing weaknesses in the old system, you won't see a
        difference.  It's just more robust and flexible.

    o Redesigned SQLString:

      - It used to derive from std::string, and while MySQL++'s
        internals did use it in place of std::string, these places
        didn't take advantage of the additional features offered
        by SQLString.  So, replaced all those uses with std::string.

      - All the remaining uses are MySQL++ public interfaces that
        need to be able to accept any of many different data types,
        and we want that data to be automatically converted to a
        SQL-compatible string form.  Because it no longer has the
        parentage to be a general-purpose string type and MySQL++ has
        a new contender for that role (String), renamed SQLString to
        SQLTypeAdapter to reflect its new, limited purpose.  ("STA"
        for short.)

      - Since we don't have the std::string base class to manage the
        string buffer any more, using the same reference counted
        buffer mechanism as String.  In addition to saving code by
        not creating yet another buffer management mechanism, it means
        objects of the two classes can share a buffer when you assign
        one to the other or pass one to the other's copy ctor.

      - Added many more conversion ctors.

      - STA interfaces using the 'char' data type now treat them as
        single-character strings instead of one-byte integers, as
        does the Standard C++ Library.

      - Added mysqlpp::tiny_int interfaces to STA to replace the
        former char interfaces for those needing one-byte integers.

    o As a result of the ColData -> String redesign, removed
      Row::raw_*().  Before String copies were efficient, this
      was helpful in accessing BLOB data efficiently.  It was also
      required back when ColData didn't deal correctly with embedded
      null characters, but that reason is gone now, too.

    o Row::operator[](const char*) no longer unconditionally throws the
      BadFieldName exception when you ask for a field that doesn't
      exist.  It will still throw it if exceptions are enabled, but if
      not, it'll just return an empty String.  This was necessary to
      make the SSQLS subset and field order independence features work.

    o Similarly, Result::field_num() returns -1 when exceptions are
      disabled and you ask for a field that doesn't exist.

    o You can now use the OptionalExceptions mechanism to disable
      exceptions on const MySQL++ objects.

    o Redesigned query result classes:

      - Instead of Result deriving from ResUse, the two derive from
        a common base class -- ResultBase -- containing the bits that
        are truly the same between them.  Before, Result inherited
        several methods that didn't really make sense for "store"
        query result sets.

      - Renamed Result to StoreQueryResult and ResUse to UseQueryResult
        so it's clearer what each is for.

      - Renamed ResNSel to SimpleResult.

      - Made all SimpleResult data members private and hid them behind
        const accessor functions of the same name.

      - The result set classes all used to be friends of Connection
        for various lame reasons.  Since they are created by Query,
        and Query has a good reason for a strong relationship with
        Connection, moved Connection access out of each result set
        class into the code in Query that creates that type of result
        set object.

      - StoreQueryResult now derives from vector<Row> in addition to
        ResultBase; it used to merely emulate a vector of Rows, poorly.
        It can now dispose of the MYSQL_RESULT at the end of object
        construction, because it creates all the Row objects up front
        instead of on the fly.  And as a result of *that*, operator[]
        returns by reference instead of by value, operator -> works
        correctly on iterators, all STL algorithms work, etc., etc.

      - IMPORTANT COMPATIBILITY BREAK: because we used fetch_row()
        stuff in Result previously, it was okay to index past the
        end of the result set: you'd just get a falsy Row when you
        did this, just as happens when doing the same thing in a
        "use" query.  The simple1 and simple2 examples did this,
        so it's likely that code exists that takes advantage of this
        misfeature.  New versions of these examples show how to index
        through a StoreQueryResult without running past its end.

      - ResUse used to delay creation of its FieldNames and FieldTypes
        objects until the point of need.  This had several implications
        for thread and exception safety that we fix by just creating
        them in the ctor.  If your code is multi-threaded and was
        avoiding certain usage patterns due to crashes, it's worth
        trying your preferred way again.

      - Result sets create a few data structures to hold information
        common to all rows in that set.  The row objects need access
        to these shared data structures, so on creation each gets
        a pointer back to the result set object that creates it.
        This was efficient, but required that a result set object
        outlive any row objects it creates.  Now these shared data
        structures are reference-counted, decoupling the lifetime of
        the child row objects from their result set parent.

      - Copy operations for result sets used to actually be "moves"
        before, for efficiency.  (MySQL++ itelf only copied result
        sets in returning them by value from the query execution
        methods of Query, so this was acceptable if you didn't do
        anything uncommon with these objects.)  Reference counted
        data structures allow us to have copy semantics now without
        sacrificing efficiency.

      - You can now use Query::storein() with an STL container of Row
        objects now, instead of having to use SSQLSes.  The lifetime
        issue guaranteed a crash if you tried this before.

      - Removed a bunch of unnecessary alias methods:

        - columns() -> num_fields()
        - names()   -> field_names()
        - rows()    -> num_rows()
        - types()   -> field_types()

      - Renamed several methods for grammar reasons:

        - fields(unsigned int)      -> field(unsigned int)
        - names(const std::string&) -> field_num(const std::string&)
        - names(int)                -> field_name(int)
        - types(int)                -> field_type(int)

      - Removed several "smelly" methods:

        - purge()
        - raw_result()
        - reset_names()
        - reset_field_names()
        - reset_types()
        - reset_field_types()

    o Field class used to just be a typedef for the corresponding C
      API class.  Now it's a real C++ class providing a more MySQL++
      sort of interface, plus good OO things like information hiding
      and implementation detail abstraction.  This changes several
      things about the interface.

    o Fields class was basically a specialized std::vector work-alike
      for dealing with the C API to get access to MYSQL_FIELD objects
      and present them as contained Field objects.  New Field type
      let us replace it with "typedef std::vector<Field> Fields"

    o Major improvements to the quoting and escaping mechanisms:

      - Replaced almost all of the type-specific interfaces in manip.h
        with a single version taking STA.  The compiler can convert
        almost anything to STA without losing any information we need
        for correct quoting and escaping.  This has the side benefit
        that we can now do correct quoting and escaping for more data
        types now, including plain C and C++ string types.

      - Fixed a bug in quote_double_only manipulator for String: was
        using single quotes by mistake.

      - Escaping and quoting only works in instances where MySQL++
        can tell you're building a SQL query and are using a data type
        that requires it.  This affects many things, but the one most
        likely to cause trouble is that inserting MySQL++'s quoting
        and escaping manipulators in non-Query ostreams is now a no-op.

      - Added escape_string() member functions to Query and
        SQLQueryParms::escape_string(), and removed the global function
        of the same name.  Because these are tied indirectly to a
        Connection object, this also has the effect that escaping is
        now aware of the current default character set used by the
        database server.  There's only one case where this isn't done
        now, and that's when we're disconnected from the server.

      - Previous two items form a trade-off: if your code was depending
        on MySQL++ to get SQL escaping and it no longer happens for
        what we consider a good reason, you can build a replacement
        mechanism using these new functions.  Quoting needs no special
        support in MySQL++.

      - Removed 'r' and 'R' template query parameter modifiers,
        which meant "always quote" and "always quote and escape"
        regardless of the data type of the parameter.  There are no
        corresponding manipulators (for good reason), so the removal
        restores symmetry.

    o Created DBDriver class from code previously in Connection and
      Query to almost completely wrap the low-level MySQL C API:

      - Connection creates a DBDriver object upon connection and
        passes a pointer to it down to Query objects it creates.
        In turn, they pass the pointer on to any of their children
        that need access to the C API.

      - Nothing outside DBDriver calls the C API directly now, though
        DBDriver leaks C API data structures quite a lot, so this
        feature doesn't constitute "database independence."  See the
        Wishlist for what must be done to get to that point.

    o Completely redesigned the connection option setting mechanism:

      - There's now just a single Connection::set_option() method that
        takes a pointer to the abstract Option base class, and there is
        an Option subclass for every connection option we understand.
        Thus, type errors are now caught at compile time instead of
        at run time.

      - Replaced Connection::enable_ssl() with SslOption class.

      - Enabling data compression and setting the connection timeout
        are no longer set via parameters to Connection interfaces.
        These are now set with CompressOption and ConnectTimeoutOption.

      - Similarly, removed client_flag parameters from Connection's
        ctor and connect() method and added corresponding Option
        subclasses.  There's about a dozen, so rather than list them
        here, look for similarly-named classes in lib/options.h.

    o Added Connection::count_rows() to execute "SELECT COUNT(*) FROM
      tablename" queries for you.

    o Moved Connection::affected_rows(), info() and insert_id() methods
      to class Query, as they relate to the most recently-executed
      query, not to the connection.

    o Several method name changes in Connection:

      - client_info()   -> client_version()
      - host_info()     -> ipc_info()
      - proto_info()    -> protocol_version()
      - server_info()   -> server_version()
      - stat()          -> status()

    o Removed Connection::api_version().  It does the same thing as
      client_version().

    o Lots of changes to Date, DateTime, and Time classes:

      - If you use the default constructor for DateTime and don't
        subsequently set its year, month, day, hour, minute or second
        data members to nonzero values, it becomes the SQL function
        "NOW()" in a query string.  You can also use DateTime::now()
        as syntactic sugar for this.

      - As a result of above, had to hide all of DateTime's data
        members behind accessor functions, to keep the state of the
        object consistent.  (If it's initialized as "now" and you
        give it an explicit year value, say, it is no longer "now",
        so the setter has to clear the now-flag.)  There are getters
        and setters for year, month, day, hour, minute and second,
        all named after the member.

      - Did the same for Date and Time for consistency, even though it
        isn't technically required.

      - The sql_timestamp typedef now aliases DateTime instead of Time.

      - Renamed template class DTbase<T> to Comparable<T>.  The fact
        that it's the common base class of all date and time classes
        is irrelevant; making subclasses comparable is what it does,
        so that's what it should be named after.

      - Added a DateTime ctor taking discrete year, month, day, hour,
        minute, and second values.

      - Implicit conversion from stringish types to the date and time
        types is no longer allowed.  This is part of the "Waba"
        Null<T> patch mentioned above; allowing implicit conversions
        would break this new feature.

      - Added operator std::string and str() methods to all of these
        classes.  Adding this to the existing operator << support, you
        now have several ways to convert these objects to string form.

      - Added time_t conversion to Date and Time classes.  DateTime
        already had it, since it's more legitimate to convert time_t
        to DateTime, but you could already "slice" it with something
        like Time(DateTime(time(0))) so there's no point pretending
        you can't get from time_t to Date or Time.  Might as well
        legitimize it.

    o Improved tiny_int class:
        
      - Turned it into a template parameterized on the value type so
        you can get both signed and unsigned TINYINTs

      - Changed the sql_tinyint and sql_tinyint_unsigned typedefs to
        use mysqlpp::tiny_int<VT> instead of raw chars

      - Added a bool conversion ctor and operator, and typedef'd it
        to sql_bool and sql_boolean to match MySQL server behavior

    o Added many more sql_* typedefs.  We now have a typedef for every
      type the MySQL server knows about, including those it supports
      just for compatibility with other database servers.

    o Changed the sql_*int* typedefs to use integer types of the same
      size as the MySQL server.  (Run test/inttypes.cpp to test it.)

    o Added copy ctor and assignment operator to Row.

    o Row::operator[]() takes int now instead of unsigned int.
      This finally (!) makes it possible to say row[0] without the
      compiler giving an ambiguous overload error.

    o Changed all uses of row.at(0) in the examples to row[0]

    o Added operator[] to all classes that only had at().

    o Query now automatically resets itself unless the query fails
      or you're using template queries.  In either case, the contents
      of the query's internal buffers are considered precious,
      either for debugging, or future queries.  Except when using
      template queries, this means you may be able to avoid calling
      Query::reset() entirely.  It's still safe to call reset()
      as before, just unnecessary most of the time.

    o Removed reset_query parameter from all Query methods.  It was
      almost completely broken before, and above change does what
      was really wanted to begin with.

    o Query::store_next() and Result::fetch_row() no longer throw
      the EndOfResults and EndOfResultSets exceptions; these are not
      exceptional conditions!  These methods simply return false now.

    o Removed examples/usequery.cpp: there's no essential difference
      between what it did and what examples/simple3.cpp does now as
      a result of the previous change.

    o Added Query::exec(void), paralleling Query::execute(void).

    o Removed Query::preview().  The most direct replacement is str(),
      which has always done the same thing.

    o You can now insert a Query object into an ostream to get a copy
      of the built query.  This means Query::str() is only necessary
      when using template queries.

    o Removed overloads of Query::execute(), store(), and use()
      that take const char*.  It was redundant because const char*
      converts implicitly to STA, for which overloads already exist.

    o Renamed Query::def to Query::template_defaults to make its
      purpose clearer.

    o Query::error() now returns const char*, not a std::string by
      value.  There's no point in making a copy of the error string.
      The method is now const as well, as it doesn't change the
      Query object.

    o Added Query::errnum(), which just wraps Connection::errnum().

    o Added error number parameters and accessor functions to BadQuery,
      ConnectionFailed and DBSelectionFailed exceptions, to preserve
      the state of Connection::errnum() at the point of the exception,
      so you don't have to rely on this value remaining unchanged
      during the exception throw process.  All places that use these
      exceptions now include this value where possible.  Thanks for the
      initial patch go to Jim Wallace.

    o Removed Lockable mechanism from Connection and Query; it was
      conceptually flawed.  See the new user manual chapter on
      threading for advice on using MySQL++ safely without locking.
      There is mutex locking now in ConnectionPool, but that's it.

    o Connection::query() now takes an optional query string, allowing
      the returned Query object to start off with a value.  Especially
      useful when the query string is static, either because it's
      a simple query or because it's a template.  You can now build
      chains like "if (conn.query("CREATE INDEX ...").exec()) { ..."

    o Added Connection::thread_aware(), thread_end(), thread_id()
      and thread_safe().  See user manual's threading chapter for
      explanations.

    o Renamed "success" data members in Connection, Query and
      SimpleResult (neé ResNSel) to "copacetic_", making them private
      if they weren't before.  This better reflects their actual
      use, which isn't to say that there has necessarily been actual
      success, but rather that everything's okay with the object.

    o Removed success() member functions from above classes.  All can
      be tested in bool context to get the same information.

    o Replaced all operator bool()s in MySQL++ classes with safer
      alternatives.  See http://www.artima.com/cppsource/safebool.html
      Thanks to Jonathan Wakely for much helpful commentary, advice,
      and code used in these mechanisms.

    o Decoupled Connection::copacetic_ from Connection::is_connected_.
      It is now possible for the object to be copacetic without being
      connected.  However, if it tries to connect and fails, then
      it is not copacetic.  If it is copacetic and not connected, it
      means we haven't even tried to connect yet, a useful distinction.

    o Collapsed Connection's host, port, and socket_name down into
      a new combined 'server' parameter which is parsed to determine
      what kind of connection you mean.  These interfaces are still
      compatible with v2.3 and earlier up through the port parameter.
      There are differences beyond this.

    o Added TCPConnection, UnixDomainSocketConnection and
      WindowsNamedPipeConnection subclasses for Connection giving
      simpler construction and connect() method interfaces for
      instances where you know what kind of connection you want at
      compile time.

    o Changed Connection::ping() return value from int to bool.

    o Renamed NullisNull to NullIsNull -- capital I -- and similar for
      NullisZero and NullisBlank.

    o It's now a compile-time error to try to convert a MySQL++
      representation of a SQL null to any other data type, rather
      than a run-time error as in previous versions.  Removed
      BadNullConversion exception as a result.

    o Way back in v1.7.x we used the BadQuery exception for all kinds
      of exceptional conditions, not just bad queries.  Replaced
      most of these in v2.0.0 with new dedicated exceptions, but a
      few remained:
      
      - Errors that occur during the processing of a "use" query after
        the query itself executes correctly now throw UseQueryError.
        It's not a "bad query", because the query executed
        successfully.  It just choked during subsequent processing,
        so it's a different exception.  Thanks for this patch go to
        Jim Wallace.

      - Replaced BadQuery exceptions thrown in Row constructor due
        to bad ctor parameters with new ObjectNotInitialized exception
        This is also Jim Wallace's work.

    o The examples now all use getopt() type command line options
      instead of positional options.  This makes it possible to
      pass options in any order, leave at their default options that
      used to be in the middle of the sequence, and offer different
      subsets of options for different programs.  Also allows for
      special internal-use options, like -D passed by dtest to let
      examples change their behavior when run under dtest to produce
      only predictable output.

    o Split old libutil functionality into two modules, one holding
      all the "print data" functions, and another holding all the
      command line parsing stuff.  This makes it easier for newbies
      to ignore the command line stuff, treating it like a black box.
      The wish to understand the "print data" routines is much more
      common, so the two needed to be disentangled.

    o Renamed examples' libutil to libexcommon.

    o Removed connect_to_db() libutil function.  It combined command
      line parsing, which users don't care about, with database
      connection establishment, which they do care about.  Now the
      examples just call out to libexcommon to parse the command
      line, and use the values they get back to explicitly make the
      connection, so it isn't hidden.

    o Removed cchar and uint typedefs.

    o Redesigned dbinfo example's output to be easier to read.

    o Fixed an output formatting bug created in 2.3.0 that caused the
      tabular output from examples to not line up.

    o Renamed examples/tquery.cpp to tquery1.cpp.  Created tquery2.cpp
      to demonstrate passing parameters via a SQLQueryParametrs object
      instead of discretely.  Created tquery3.cpp for testing unquoted
      template parameters, such as integers.

    o Renamed fieldinf1.cpp example to fieldinf.cpp, and simplified
      its output so it can be part of the dtest sequence.

    o Renamed examples/xaction.cpp to transaction.cpp.  It created too
      much cognotive dissonance whenever thinking about both it and
      lib/transaction.cpp.

    o Added examples/deadlock.cpp, to test handling of exceptions due
      to server-side transaction deadlock detection.  Also added
      code to resetdb to create a table needed to test this.
      Initial version created by Jim Wallace to test the value of
      all his BadQuery exception work, with reworking by me.

    o Greatly expanded dtest suite.  Primary change is that we now
      have a handful of unit tests, where in v2.3.2 we only tested
      a subset of the examples.  Still very low coverage ratio,
      but it's a big improvement.

    o Optimized #includes, especially in lib/*.h to reduce
      dependencies and thus compile time when one of these changes.

    o Fixed a typo in RPM filename generation that prevented -devel
      RPM from recognizing that the corresponding MySQL++ library
      RPM was installed.

    o RPM spec file improvements by Remi Collet.

    o Renamed NO_LONG_LONGS to MYSQLPP_NO_LONG_LONGS to avoid a risk
      of collision in the global macro namespace.
    
    o First cut at Xcode2 project support.  Testing needed!

    o Debug build of library on VC++ and Xcode have a _d suffix now
      so you can have both versions of the library installed without
      conflict.

    o Moved the VC++ 2003 project files into a new vs2003 subdirectory
      because there are so many of them.  Also created vs2005
      subdirectory for VC++ 2005 and 2008 compatible project files.
      2005 makes an even bigger mess of the directory containing
      the .sln file, so the incentive is bigger.  Plus, we have to
      disable several things to get VC++ 2003 to build MySQL++ now,
      so we need a special 2005+ version of the project files for a
      complete build, if the user has one of the newer compilers.

    o ...plus dozens of small bug fixes and internal enhancements,
      many documentation improvements, and expansion of support for
      newer operating systems and compilers.


2.3.2, 2007.07.11 (r1669)

    o Previous release's const_string change caused more problems
      than it fixed.  This release contains the real fix. :)

    o New Connection::set_option() handling deals with the multi
      statements option correctly again.  examples/multiquery now
      runs again as a result.

    o Added new unit testing script, called dtest.  See the
      HACKERS file for details.  (This tool caught the previous
      two problems!)

    o Squished a GCC pedantic warning.  Thanks for the patch go to
      Andrew Sayers.


2.3.1, 2007.07.10 (r1659) The "After the Fireworks" release

    o const_string objects now keep a copy of their data, not
      just a pointer to it.  This is less efficient, but necessary
      to allow SSQLS to work with BLOBs.  Without this, we were
      seeing segfaults due to accessing freed memory pointed to
      by the const_string, because the underlying object went
      out of scope.

    o Fixed many more potential embedded null handling problems
      in manip.h.

    o MySQL++ can now optionally reference MySQL C API headers as
      being in a mysql subdirectory, a common thing on *ix systems,
      by defining MYSQLPP_MYSQL_HEADERS_BURIED before #including
      mysql++.h.

    o Restored ColData_Tmpl<T>::get_string(), removed in v2.3.0,
      along with warnings in the docs saying why you don't want
      to use it, and what your alternatives are.

    o VC++ and MinGW builds now define the HAVE_MYSQL_SSL_SET
      macro, which lets you use the C API's SSL features.
      This assumes your C API library does actually have these
      features enabled, which is the case with the official binary
      releases on Windows.  (Builds on *ix systems continue to
      test for these features at configure time.)

    o Fixed simple examples-only Makefile generation, for RPMs.


2.3.0, 2007.07.02 (r1645)

    o Added Query::for_each() and Query::store_if() methods
      proposed by Joel Fielder, and added examples for each.

    o It's now possible to store BLOB data in an SSQLS.  It's not
      foolproof, so added a section to the user manual (5.9) to
      document the method.  Also, changed examples/cgi_jpeg to use
      this new mechanism, instead of the ugly "raw row data" method
      it used to use.

    o Revamped Connection::set_option() handling.  These options
      used to be queued up, and applied only just before actually
      establishing the connection.  This made error reporting less
      helpful because the diagnostic was separated from the cause.
      Plus, the error messages were misleading to begin with.  Now,
      set_option() takes effect immediately if the connection is not
      yet up (excepting one special option that can actually be set
      after the connection is up) and issues better diagnostics when
      it detects errors.

    o Connection::connect() used to set a few options in such a
      way that the user couldn't override them.  Now it's smart enough
      to set them with the desired default values only when we see
      that the user hasn't given them other values.

    o SQLString can now be initialized from a mysqlpp::null,
      giving a "NULL" string.  This is useful for template queries.
      Patch by Michael Hanselmann.

    o resetdb error message about mixing library and header version
      numbers is now more explicit.

    o Changed BadConversion exception's "what" message text to be
      more like the other exceptions.  The inconsistency lead one
      to incorrectly copy-paste code from another exception handler,
      expecting it to behave the same way.  Now it does.

    o Added Row::raw_size(), as a shortcut for Row::at().size().

    o ssqls-pretty now detects when it's being run from within
      the MySQL++ distribution tree and gives a different -I flag
      to the compiler, so that it picks up the distribution headers
      instead of those that may be on the system already.

    o The quote manipulator now works for char[] correctly.
      Thanks for this patch go to Andrew Sayers.  (It's always
      worked for char*, but C++ doesn't consider that to be the
      same type, so it used the generic quote handling path,
      which doesn't do anything for char[].)

    o Fixed a build bug on older Solaris versions where the
      test for the C API library was erroneously failing, stopping
      the configuration process.

    o Simplified mysql_shutdown() level argument detection.
      Already had to do a version number ifdef check for the
      Windows case, so there's really no point to doing it with
      autoconf on Unixy platforms.  Moved version number check
      into lib/connection.cpp, and nuked the separate autoconf and
      Windows tests.

    o Removed dependency of sql_types.h on myset.h and (indirectly)
      datetime.h.  Now we only define sql_* typedef aliases for those
      MySQL++ types if the headers are included before sql_types.h.

    o Fixed a typo in one of the storein_sequence() template
      overloads, which is apparently rarely (or never?) used, because
      no one reported the compiler error you'd get if you tried.

    o Fixed a few more embedded null handling problems.

    o ColData used to keep two copies of all data it held.
      Now it keeps just one.

    o Fixed install.bat script to track the unified Bakefile change
      and the lack of separate debug and release builds under MinGW.

    o Yet another STLport + Query memory leak fix.

    o Squished a warning in newer GCCs having to do with identifier
      shadowing.  Patch by Jonathan Wakely.

    o Fixed a null-termination bug in Query::parse().  If you
      somehow constructed a query string without a terminating null
      character, then tried to parse it as a template query, it could
      walk off the end of the string.  Patch by Worster Chen.

    o Removed MYSQLPP_EXPORT tag from FieldNames and FieldTypes
      class declarations, as this can cause problems in programs
      that use vector<string> in VC++.  It has to do with multiply
      defined templates, since these classes derive from that
      template, and VC++ can't resolve the conflict without help.
      Since these classes aren't actually used outside the library,
      this shouldn't cause a problem.  Patch by Nils Woetzel.

    o Partial fix to Doxygen PDF build on RHEL4 and 5.  Needs
      hand-coaxing to complete successfully on RHEL4, and doesn't
      yet work at all on RHEL5.

    o Shortened the "no*" options to the bootstrap script, so that
      the usage message fits on a single line.

    o Added "nodoc" bootstrap script option, for disabling the
      documentation build during the dist target build.  Allows for
      building binary RPMs on CentOS 5.0, where doc building is
      currently broken.

    o Removed the updel example program.  It was kind of silly,
      and if you were to rewrite it today, you'd use for_each() anyway.

    o Lots of documentation improvements.


2.2.3, 2007.04.17 (r1538) The "Tax Day" release

    o Previous version left examples/vstudio/* out of the tarball
      by accident.

    o Improved generation of RPM temporary build directory path
      name generation.  Was using a hacked variant of the Fedora
      Packaging Guidelines' second best choice.  Now we're using
      the choice they recommend most highly, without changes.

    o Removed unnecessary resources from vstudio/wforms example.

    o Minor URL fix in refman


2.2.2, 2007.04.13 (r1526) The "Nervousmaking Friday the 13th" release

    o More small fixes to embedded null handling in Query.

    o Fixed a bug in single-parameter template query handling.

    o Added tquery example, to demonstrate proper use of template
      queries.  Previously, resetdb was the only exemplar, and
      it wasn't really suited for that.  This example also tests
      the previous item.

    o Added examples/vstudio/mfc, allowing us to improve the way
      we demonstrate Unicode handling.  Old way wasn't realistic.
      On *ix, people will depend on the terminal code to handle
      UTF-8.  On Windows, users are almost certain to be writing
      a GUI program, which requires different Unicode handling
      than the old examples showed.

    o Removed explicit Unicode conversion stuff from command line
      examples, and reworked the Unicode chapter in the user
      manual.
    
    o Added examples/vstudio/wforms to show integration with
      C++/CLI and Windows Forms.  Documented this in README.vc.

    o Rewrote load_file and cgi_image examples to be more
      useful, renaming them to load_jpeg and cgi_jpeg along
      the way.  Also, resetdb now creates a second table in the
      sample database for these two examples' use.  Also, added
      examples/logo.jpg to the distribution as sample data for
      these examples.

    o Limited the ostream base class casting stuff in Query to
      VC++ 2003, which is the only platform that really needed it.
      VC++ 2005 emits a warning with that hack in place, and on
      other platforms it's just replicating work that the compiler
      does already.

    o Added library version information to main library target
      so that systems that version shared libraries work as
      expected.  Thanks for this patch go to Jack Eidsness.

    o Merged much of the diffs between Remi Collet's RPM spec file
      into the official one.

    o Reorganized the doc subdir a bit.  Generated HTML is now all
      under doc/html instead of scattered under other subdirs,
      and renamed doc/README.mysql++ to doc/README.manuals.

    o Improvements to top-level manual building make targets:
      manuals now only rebuild at need, it's easier to request
      a rebuild of all manuals, and we force a rebuild attempt
      before building the distribution tarball so we don't ship
      outdated manuals.

    o Added ability to run examples under gdb using exrun,
      using same mechanism as we currently have for valgrind.
      Thanks for this patch go to Michael Hanselmann.

    o Added "Important Underlying C API Limitations" chapter to the
      user manual, to cover problems we keep seeing on the
      mailing list that are the result of ignorance of the way
      libmysqlclient behaves, not bugs MySQL++ is really in a
      position to fix.


2.2.1, 2007.02.28 (r1433)

    o Fixed the new localtime() alternative selection code
      for VS2003 and various uses of STLport.

    o No longer inserting a null character into the query stream
      on calling one of the preview() functions.  This was harmless
      in v2.1, which used C strings more extensively, but began
      causing problems in v2.2 due to its wider use of C++ strings.

    o Fixed a bug in the Connection copy ctor where it didn't
      completely initialize the object.

    o Optimized Query::preview_char() a bit.  Patch by Jonathan
      Wakely.

    o Reordered directory list used by autconf when locating the
      MySQL C API library.  The list is now ordered with the
      most likely locations for the library first, so we're less
      distracted by incorrect libraries.  This fixes a specific
      build error under RHEL4 with recent versions of MySQL 5.0.


2.2.0, 2007.01.23 (r1417)

    o ColData, const_string, and SQLString can now be constructed
      with an explicit length parameter.  Furthermore, Query
      class's execute(), store() and use() call chains terminate
      in a version taking an explicit length parameter, instead
      of one taking a simple C string.  Together, this means
      that it's now easier to handle data from the SQL server
      containing nulls.  The library is almost certainly not yet
      capable of handling embedded nulls in all cases, but this
      is a big first step towards that.

    o Can now construct a DateTime object from a time_t, and
      convert a DateTime back to a time_t.  Patch by Korolyov Ilya.

    o Changed the way we're handling exported functions in the
      Windows DLL case so that it works more reliably under MinGW.

    o Added proper copy semantics to Connection, so that you get a
      new connection with the same parameters, not just a bitwise
      copy of the object.

    o Using an explicitly thread-safe variant of localtime() for
      time conversions where one is available.

    o Removed ListInsert template from myset.h.  This wasn't used
      within the library, and was never documented, so I'm betting
      that no one actually uses it.

    o Result::copy() was not copying the exception flag in
      all cases.  Fix by Steven Van Ingelgem.

    o Added exrun shell script and exrun.bat files to distribution,
      to avoid linkage errors when running the examples while
      you still have an older version of MySQL++ installed.

    o Renamed MYSQLPP_LIB_VERSION to MYSQLPP_HEADER_VERSION, as
      what it really encodes is the version number in the mysql++.h
      file you're using, not the actual library version number.

    o Added mysqlpp::get_library_version(), which returns the
      library version number at build time.  Between this and
      the header version constant, you can check that you're not
      mixing MySQL++ header and library versions.

    o resetdb example uses these new version number affordances to
      double-check that you're not mixing libraries and headers
      from different versions.  This happens easily unless you
      take care of it (such as by using exrun) when you have one
      version of MySQL++ installed and you're trying to build and
      test a new version without blowing away the old one first
      or overwriting it.

    o No longer using recursive Makefiles on Unixy platforms
      or split lib + examples project files on VC++.  Everything is
      handled by a single top-level Makefile or project file, which
      is simpler for the end user, and makes better dependency
      management possible.

    o When looking for the MySQL C library on systems using
      autoconf, looking in .../lib64 wherever we are also looking
      in .../lib.

    o RPM build process no longer depends on Bakefile.  It means
      you have to build the examples when building an RPM even
      though they're never used within the RPM, but it's a better
      tradeoff in my opinion.

    o Updated include and library paths on Windows to reflect
      changes in the most recent MySQL installers.

    o Merged lib/defs.h and lib/platform.h into new file,
      lib/common.h.  Just cleans up the library internals.

    o Fixed build errors on Windows due to recent changes in MySQL.

    o Fixed a few memory leaks and double-deletes in Query class.

    o Fixed compatibility with STLPort's string implementation.
      Patch by dengxy at cse.buaa.edu.cn.

    o Fixed a compatibility problem between Set<> template and
      SSQLS.  Patch by Korolyov Ilya.

    o Fixed build bug in SQLQueryParms due to a character
      signedness issue on PowerPC with GCC.  Patch by Michael
      Hanselmann.

    o ~Transaction() can no longer throw exceptions.  It'll just
      quietly eat them, to avoid program termination.  Fix
      suggested by Alex Burton.

    o Fixed thread safety testing in autoconf case, accidentally
      broken during v2.1.0 development cycle.

    o Using Doxygen 1.5.1 to generate documentation.


2.1.1, 2006.04.04 (r1289)

    o MinGW and Cygwin will now build and link to mysqlpp DLLs.

    o Fixed bug in Query, causing it to initialize the "throw
      exceptions" flag incorrectly.  Thanks for this patch go to
      Joel Fielder.

    o Added -v flag for custom.pl script, which turns off the
      multiply-defined static variable fix.  Needed for VS 2003,
      which doesn't support variadic macros.  Also, added
      a diagnostic to detect the need for the -v flag, and
      suppressed the test for this feature in examples/util.cpp.


2.1.0, 2006.03.24 (r1269)

    o Converted automake and makemake files to their equivalents in
      Bakefile format.

    o Added the Transaction class, which makes it easy to use
      transaction sets in MySQL++.

    o Added xaction example to test new Transaction class.

    o Resetdb example now creates its example table using the
      InnoDB storage engine, in order to test the new transaction
      support.  Resetdb also declares the table as using UTF-8
      text; this doesn't change anything, but it does correctly
      document what we're doing.

    o Added sql_types.h header, containing C++ typedefs
      corresponding to each MySQL column type.  Using those new
      types in the type_info module, and in the SSQLS examples.

    o Replaced the way we were handling the template query
      version of Query member functions, to allow an arbitrary
      number of template query parameters.  By default, we
      now support 25 parameters, up from the old limit of 12.
      It's now possible to change just one number, run a script,
      and have a new limit.

    o Connection class does a better job of returning error
      messages if you call certain member functions that depend
      on a connection to the server before the connection is
      established.

    o Updated libmysqlclient.def for newer versions of MySQL.  (Fixes
      build errors having to do with mysql_more_results() and
      mysql_next_result().

    o Replaced final use of strcpy() with strncpy().

    o custom.pl now runs without complaint in strict mode, with
      warnings turned on.  Thanks for this patch go to "Waba".

    o Fixed a bug in custom.pl where incorrect code would be
      generated for some SSQLS set() methods.  Thanks for this
      patch go to "Waba".

    o SSQLS structures now support long and unsigned long fields.
      Thanks for this patch go to "Waba".

    o It's now possible to put SSQLS definitions in a header
      file used by multiple modules in a program without
      getting multiple static member definition errors.  See the
      documentation for details.  Thanks for this patch go to
      Viktor Stark.

    o Moved the definition of the 'stock' SSQLS out of the
      custom*.cpp example files and into a new stock.h file.
      Also, #including that file in the util module to test out
      the new SSQLS multiple static definition fix.

    o Using all of the digits of precision guaranteed by the
      IEEE 754 spec when stringizing floating point numbers
      to build queries.  Previously, we would use the platform
      default, which can be as few as 6 digits.

    o Removed lib/compare.h.  Not used within the library, never
      documented, and nobody seems to want to defend it.


2.0.7, 2005.11.23 (r1147)

    o Added explicit mysqlpp namespace qualifiers to generated code in
      custom*.h so you can use SSQLS in places where it doesn't make
      sense to say "using namespace mysqlpp" before the declaration.
      Also updated some of the examples to not have this "using"
      declaration to make it clear to users that it isn't needed, if you
      want to use explicit namespace qualifiers as well.  Thanks for
      this patch to Chris Frey.

    o Removed an apparently useless unlock() call from ResUse; there is
      no nearby lock() call, so if this unlock() is in fact necessary,
      it shouldn't be here anyway, because the two calls should be
      nearby each other.  Thanks for this patch to Chris Frey.

    o Fixed Query ostream initialization bug affecting SunPro CC (at
      least).  While this bug violates the Standard, it doesn't affect
      many real compilers because they don't enforce this rule.  Fixed
      by Chris Frey.

    o Previously, we only used the C99 style "long long" support when
      building under GNU CC.  This is now the default.  This should
      allow the code to work under SunPro CC.

    o Added another dynamic cast needed for proper Query ostream
      subclass overloading under VC++.  (7.1 at least...)

    o Detecting whether MySQL is built with SSL support on platforms
      using autotools.  Needed on some old Sun systems, for instance.
      Thanks for this patch to Ovidiu Bivolaru.

    o Fixed a potential memory bug in ColData's conversion to SQL null.

    o Many minor packaging tweaks.  (README clarifications, file
      permission fixes, better adherence to GNU packaging standards,
      etc.)

    
2.0.6, 2005.09.28 (r1123)

    o Fixed makemake.bat so it works on cmd.exe, not just 4NT.

    o Documentation fixes.


2.0.5, 2005.09.13 (r1114)

    o Visual C++ build now requires GNU make.  It is tested to work
      with either the Cygwin or the MinGW versions.  The previous
      version of MySQL++ used nmake.  This change enabled the
      following features:

        o Debug and Release versions are both built into
          separate subdirectories.

        o Dependency tracking for release version works
          correctly now.  (Previously dependencies worked
          only for debug version.)

        o 'make clean' removes release version binaries
          in addition to debug versions.

    o MinGW makemake support updated to support new release/debug
      subdirectory system.  This is probationary support, since
      this code currently can't be built as a DLL.  As a result,
      it is no more useful than the Cygwin version, for licensing
      reasons.

    o Several fixes to allow building on Solaris 8.  These fixes may
      also help on other SVR4-derived systems.

    o Removed Borland C++ makemake support, because this version
      of the library does not work completely, and there seems
      to be almost no user interest in fixing it.
      
    o Clarified "Handling SQL Nulls" section of user manual's
      Tutorial chapter.


2.0.4, 2005.08.29 (r1076)

    o Made mysql_shutdown() second parameter autoconf check less
      sensitive to compiler pedantry.

    o VC++ library Makefile is now smart enough to re-create the
      import library, if it is deleted while leaving the DLL alone.

    o Added libmysqlclient.def to tarball.

    o Reworked most of the top-level README* files.

    o Renamed LGPL file to LICENSE.


2.0.3, 2005.08.25 (r1060)

    o Visual C++ makemake system updated to build both debug and
      release versions of library DLL.

    o Fixed bug in simple1 example that caused crashes on Windows.

    o Doing UTF-8 to ANSI text translation in simple examples now.

    o Previous two releases built libmysqlpp with wrong soname on
      autotools-based systems.  Fixed.


2.0.2, 2005.08.18 (r1050)

    o Fixes to makemake system for cmd.exe.

    o Fixed the case where the system's C++ library includes an slist
      implementation in namespace std.


2.0.1, 2005.08.17 (r1046)

    o Added new simple1 example, showing how to retrieve just one
      column from a table.  Old simple1 is now called simple2, and
      simple2 is likewise shifted to simple3.

    o Added custom6 example, showing how to do the same thing with
      SSQLS.

    o Updated user manual to cover new examples.

    o Was accidentally shipping Subversion crap with tarball.  Fixed.


2.0.0, 2005.08.16 (r1031) The "Excess Hair Removal" release

    THIS IS NOT A DROP-IN REPLACEMENT FOR MySQL++ v1.7!

    At minimum, you will have to recompile your program against
    this library.  You may also have to make code changes.
    Please see the "Incompatible Library Changes" chapter of
    the user manual for a guide to migrating your code to this
    new version:

        http://tangentsoft.net/mysql++/doc/html/userman/breakages.html

    o The library's shared object file name (soname) scheme has
      changed.  (This mainly affects POSIX systems.)
      
      The soname for the last 1.7.x releases of MySQL++ was
      libmysqlpp.so.4, meaning the fourth version of the library's
      application binary interface (ABI).  (The first ABI version
      in this scheme was that provided by 1.7.9.)  MySQL++
      2.0.0's soname is libmysqlpp.so.2.0.0.  Since the dynamic
      linker setup on some systems will create a symlink to
      that file called libmysqlpp.so.2, it's possible that this
      library could be confused with that for MySQL++ 1.7.19
      through .21, which also used this number.  Do not install
      this library on a system which still has binaries linked
      against that version of the library!

      The new scheme is {ABI}.{feature}.{bug fix}.  That is,
      the first number changes whenever we break the library's
      binary interface; the second changes when adding features
      that do not break the ABI; and the last changes when the
      release contains only internal bug fixes.  This means
      that we will probably end up with MySQL++ 3.0 and 4.0 at
      some point, so there will be further soname conflicts.
      Hopefully we can put these ABI changes off long enough
      to avoid any real problems.

    o autoconf now installs headers into $prefix/include/mysql++,
      instead of $prefix/include.  If you were using the
      --includedir configure script option to get this behavior
      before, you no longer need it.

    o Linux binary RPMs will henceforth include only the
      libmysqlpp.so.X.Y.Z file, and create any short names
      required, to allow multiple versions to be installed at
      once.  Currently, you cannot install two MySQL++ library
      RPMs at once, because they both have /usr/lib/libmysqlpp.so.X,
      for instance.

    o Replaced the Visual C++ and Borland C++ project files with
      a new "makemake" system, which creates Makefiles specific
      to a particular toolchain.  This new mechanism also supports
      MinGW and generic GCC-on-*ix.  This was done partly to reduce
      the number of places we have to change when changing the
      file names in MySQL++ or adding new ones, and partly so we're
      not tied to one particular version of each of these tools.

    o VC++ Makefiles create a DLL version of the library only
      now, so there's no excuse for LGPL violations now.
      This same mechanism should make DLL builds under other
      Windows compilers easy.

    o Added Connection::enable_ssl(), which enables encrypted
      connections to the database server using SSL.

    o Connection::create_db() and drop_db() now return true on
      success, not false.

    o Connection::create_db() and drop_db() use Query::exec()
      now, for efficiency, rather than Query::execute().

    o Removed Connection::infoo().  Apparently just there to
      save you from a typo when calling the info() method, since
      it was a mere alias.

    o Renamed Connection::real_connect() to connect(), gave
      several more of its parameters defaults, and removed old
      connect() function.  Then changed user manual and examples
      to use new APIs.

    o Replaced Connection::read_option() with new set_option()
      mechanism.  The name change matches the method's purpose
      better.  Functional changes are that it returns true on
      success instead of 0, it supports a broader set of options
      than read_option() did, and it enforces the correct option
      argument type.

    o You can now call Connection::set_option() before the
      connection is established, which will simply queue the option
      request up until the connection comes up.  If you use this
      feature, you should use exceptions, because that's the only
      way an option setting failure can be signalled in this case.

    o Removed query-building functions (exec*(), store*(),
      use()) from class Connection, and moved all the implementation
      code to class Query.  Query no longer delegates the final
      step of sending the query to the database server to
      Connection().

    o Added Connection::enable_ssl(), for turning on SSL support on
      a connection.

    o Extracted exception disabling mechanism out of the many
      classes that had the feature into a new OptionalExceptions
      base class, which all classes having this feature now
      derive from.  Also, removed all per-method exception
      handling flags.  Finally, added NoExceptions class.  With
      all of these changes, there is now a common way to disable
      exceptions with fine granularity on all objects that
      support the feature.

    o All custom MySQL++ exceptions now derive from the new
      Exceptions class.  This regularizes the exception interface
      and allows you to use a single catch() block if you want.

    o The "throw exceptions" flag is passed from parent to child
      in all situations now.  (Or if not, please report it as
      a bug.) This fulfills a promise made in the v1.7.9 user
      manual, with the cost being that some programs will see
      new exceptions thrown that they're not expecting.

    o Added a bunch of new exception types: BadOption,
      ConnectionFailed, DBSelectionFailed, EndOfResults,
      EndOfResultSets, LockFailed, and ObjectNotInitialized.
      Some of these replace the use of BadQuery, which in v1.7.x
      was a kind of generic exception, thrown when something more
      specific wasn't available.  Beware, this means that programs
      may start crashing after recompiling them under v2.0 due to
      uncaught exceptions, if they were only trying to catch BadQuery.

      There are additional instances where the library will
      throw new exceptions.  One is when calling a method that
      forces the internals to use an out-of-bounds index on a
      vector; previously, this would just make the program
      likely to crash.  Another is that the library uses the
      BadFieldName exception -- created in v1.7.30 -- in more
      apropos situations.

    o Renamed SQLQueryNEParms to BadParamCount, to match naming
      style of other concrete exception types.

    o Extracted lock()/unlock() functions from Connection and
      Query classes into a new Lockable interface class.  Locking
      is implemented in terms of a different class hierarchy, Lock,
      which allows multiple locking strategies with a single ABI.

    o Removed ResUse::eof().  It's based on a deprecated MySQL
      C API feature, and it isn't needed anyway.

    o Removed arrow operator (->) for iterator returned by Fields,
      Result and Row containers.  It was inherently buggy, because
      a correct arrow operator must return the address of an
      object, but the underlying element access functions in these
      classes (e.g. at()) return objects by value, of necessity.
      Therefore, this operator could only return the address of
      a temporary, which cannot be safely dereferenced.

    o Returned Row subscripting to something more like the
      v1.7.9 scheme: there are two operator[] overloads, one for an
      integer (field by index) and another for const char* (field
      by name).  lookup_by_name() has been removed.  Because row[0]
      is ambiguous again, added Row::at() (by analogy with STL
      sequence containers), which always works.

    o Collapsed two of the Row::value_list*() overloads into
      two other similar functions using default parameters.
      This changes the API, but the removed functions aren't
      used within the library, and I doubt they are used outside,
      either.

    o Merged RowTemplate into Row.

    o Merged SQLQuery class into Query class.

    o Query is now derived from std::ostream instead of
      std::stringstream, and we manage our own internal string
      buffer.

    o Moved SQLParseElement and SQLQueryParms into their own
      module, qparms.

    o Added multiple result set handling to Query.  MySQL 4.1
      and higher allow you to give multiple SQL statements in a
      single "store" call, which requires extensions to MySQL++
      so you can iterate through the multiple result sets.  Also,
      stored procedures in MySQL 5.0 reportedly return multiple
      result sets.  Thanks for the initial patch go to Arnon Jalon;
      I reworked it quite a bit.

    o Query::storein*() now supports more varieties of the
      nonstandard slist comtainer.  (Singly-linked version of
      STL std::list.)

    o Template query mechanism and user manual had several
      mismatches.  Made manual match actual behavior, or
      made library match documented behavior, as apropriate.
      Initial patch by Jürgen MF Gleiss, with corrections and
      enhancements by Warren Young.

    o Collapsed mysql_* date and time base classes' methods and
      data into the subclasses.  Also, DateTime no longer derives
      from Date and Time; you could get away with that in the
      old hierarchy, but now it creates an inheritance diamond,
      and allows unsupported concepts like comparing a Time to
      a DateTime.

    o Removed "field name" form of Row::field_list().  It was
      pretty much redundant -- if you have the field names, why
      do you need a list of field names?

    o ColData can convert itself to bool now.  Thanks for this
      patch go to Byrial Jensen.

    o Removed simp_list_b type; wasn't being used, and doesn't
      look to be useful for end-user code.

    o Several methods that used to take objects by value now
      do so by const reference, for efficiency.

    o Several variable and function renamings so that MySQL++
      isn't needlessly tied to MySQL.  Even if we never make
      the library work with other database servers, there's
      little point in tying this library to MySQL blindly.

    o Renamed all private data members of MySQL++ classes to
      have trailing underscores.

    o 'private' section follows 'public' section in all classes
      now.

    o Removed mysql++.hh and sqlplus.hh backwards-compatibility
      headers.

    o Added copy ctors to Date/Time classes so that they will
      work in SSQLS under GCC 4.0.0.  Without these, the compiler
      couldn't make the conversion from raw MySQL row data.

    o Fixed a bunch of GCC 4.0 pedantic warnings: added virtual
      dtors to all base classes, calling base class ctors from leaf
      classes, etc.

    o All warnings fixed under VC++ at warning level 3.  (Mostly
      harmless signedness and integer conversion stuff.)

    o Updated LGPL license/copyright comments at the top of
      several files to use FSF's new physical address.

    o Relicensed user manual under a close variant of the Linux
      Documentation Project License, as it's designed for
      documentation, which the LGPL is not.  Permission for this
      received from Kevin Atkinson and MySQL AB.

    o Added ABI and API breakages chapter to user manual.  It
      is basically a subset of this ChangeLog, with only the
      information an end-user must know when migrating between
      versions.

    o Reworked user manual's DocBook code quite a bit after
      reading Bob Stayton's book "DocBook XSL" 3/e.  Better handling
      of stylesheets, taking advantage of some superior DocBook
      features, prettier output (especially the HTML version), etc.

    o Rewrote doc/userman/README to make it clearer how to get
      started contributing to the user manual.  It's essentially a
      "getting started with DocBook" guide now!

    o Lots of small text improvements to user and reference
      manuals.  Aside from the obvious tracking of library changes,
      made a bunch of minor style and clarity improvements.

    o Added CSS stylesheets for userman and refman to
      make the HTML versions of each a) not ugly; and b) match
      tangentsoft.net.  (Yes, some may say that these are incompatible
      goals....)

    o Standardized exception handling code in the examples that
      use it.

    o Fixed a potential memory leak due to exceptions thrown from
      ResUse.  Thanks for this patch go to Chris Frey.

    o Using new "no exceptions" feature of library in simple1
      example, so it is now truly simple.

    o simple1 example no longer depends as much on util module, so
      that all of the important code is in one place.  Makes
      learning MySQL++ a little less intimidating.

    o Added new simple2 and usequery examples, to demonstrate
      the proper way to handle a "use" query, with exceptions
      disabled, and not, respectively.  Added them to the user
      manual, in the appropriate place.

    o Refactored the "print stock table" example functions
      again, to make code using them clearer.

    o UTF-8 to UCS-2 handling in examples is now automatic on
      Windows.

    o Removed debug code from Windows Unicode output examples
      that slipped into previous release.

    o resetdb example is now clearer, and more robust in the
      face of database errors.

    o Simplified connect_to_db() in examples' util module.

    o Added sample autoconf macro for finding MySQL++ libraries, for
      people to use in their own autotools-based projects.

    o Lots and lots of minor cleanups not worth mentioning
      individually...


1.7.40, 2005.05.26 (r719)

    o Multiple item form of insert() now works if you're using the
      SQLQuery class, or its derivative, Query.  Thanks to Mark
      Meredino for this patch.

    o Fixed a bug in const_string::compare(), in which MySQL++
      would walk off the end of the shorter of the two strings.
      All was well if the two were the same length.

    o ResUse::operator=() now fully updates the object, so it's more
      like the behavior of the full ctor.

    o All source files now contain a license and copyright statement
      somewhere within them.

    o Optimized mysql++.h a bit: it now #includes only the minimum set
      of files required, and there is now an idempotency guard.
      This improves compile times a smidge, but mainly it was
      done to clean up the generated #include file graph in the
      reference manual.  Before, it was a frightful tangle because
      we #included everything except custom*.h.

    o Constness fix in MySQL++ date/time classes to avoid compiler
      warnings with SSQLS.  Thanks to Wolfram Arnold for this patch.

    o Fixed some compiler warnings in custom*.h.  Thanks to Chris Frey
      for this patch.

    o Added "Submitting Patches" and "Maintaining a Private CVS
      Repository" sections to the HACKERS file.  Thanks to Chris
      Frey for the source material for these sections.  The HACKERS
      file was improved in several other ways at the same time.

    o PDF version of user manual no longer has links to the reference
      manual.  They were ugly, and they were broken anyway due to the
      way we move the PDFs after generating them.  If you want
      interlinked manuals, use the HTML version.

    o PDF version of user manual now has hard page breaks between
      chapters.

    o Removed complic1 example.  Wasn't pulling its own weight.
      Everything it is supposed to demonstrate is shown in other
      examples already.

    o Refactored print_stock_table() in examples/util module to be
      four functions, and made all the examples use various of
      these functions where appropriate.  Before, several of
      the examples had one-off stock table printing code because
      print_stock_table() wasn't exactly the right thing, for one
      reason or another.  One practical problem with this is that
      some of the examples missed out on the recent Unicode updates;
      now such a change affects all examples the same way.

    o Since so many of the examples rely on the util module, the user
      manual now covers it.  The simple1 example in the user manual
      didn't make much sense before, in particular, because it's
      really just a driver for the util module.

    o Added custom5 example.  It shows how to use the equal_list()
      functionality of SSQLS.  Thanks to Chris Frey for the original
      version of this program.  (I simplified it quite a bit after
      accepting it.)

    o New user manual now covers the value_list(), equal_list() and
      field_list() stuff that the old manual covered but which was
      left out in previous versions of the new manaul.  Most of the
      examples are the same, but the prose is almost completely new.
      This new section includes the custom5 example.

    o Every declaration in MySQL++ is now documented in the reference
      manual, or explicitly treated as "internal only".

    o Improved docs for MySQL++'s mechanism to map between MySQL
      server types and C++ types.  Initial doc patch by Chris Frey,
      which I greatly reworked.

    o Improved a lot of existing reference manual documentation while
      adding the new stuff.

    o Expanded greatly on the exception handling discussion in the user
      manual.

    o Added all-new "Quoting and Escaping" section to the user
      manual's Tutorial chapter.  Moved some existing comments on
      quoting and escaping around and added some new ones to other
      sections as a result.

    o Added all-new "Handling SQL Nulls" section to the user manual's
      Tutorial chapter.

    o Many improvements to the Overview section of the user manual.

    o Row::operator[] reference now explains the right and wrong way to
      use the values it returns.  This is in response to a mailing list
      post where someone was incorrectly using this feature and getting
      a bunch of dangling pointers.

    o Updated Doxyfile so 1.3.19.1 parses it without warnings.  Still
      works with versions back to 1.2.18, at least.  (These are
      the versions shipped with Fedora Core 3 and Red Hat Linux 9,
      respectively.)

    o Using a superior method to make Doxygen ignore certain sections
      of the source code.  Between this change and the fact that
      everything not so ignored is documented, Doxygen no longer
      generates any warnings.

    o Lots of code style updates.  Everything should now be consistently
      formatted.


1.7.35, 2005.05.05 (r601) The "Cinco de Mayo" release

    o Added a "how to use Unicode with MySQL++" chapter to the user
      manual.  (Too bad "Cinco de Mayo" doesn't have any accented
      characters.  That would be just _too_ precious.)

    o VC++ examples now use the Unicode Win32 APIs, so they can display
      Unicode data from MySQL++.

    o Added an optional conversion function to examples/util.cpp to
      handle the conversion from UTF-8 to UCS-2 on Win32.

    o Moved "brief history of MySQL++" from intro section of refman to
      intro section of userman.

    o Lots of small bits of documentation polishing.
    
    o Made some minor constness fixes.  Thanks to Erwin van Eijk
      for this patch.

    o Made some warning fixes for GCC 4.0.  Not all warnings are
      fixed, because some of the needed changes would break the ABI.
      Thanks to Chris Frey for this patch.

    o Added lib/Doxyfile to distribution.
    

1.7.34, 2005.04.30 (r573)

    o Added a multiple-insert method for Query, which lets you insert
      a range of records from an STL container (or the whole thing,
      if you like) in a single SQL query.  This is faster, and it
      reduces coding errors due to less repetition.  Thanks to Mark
      Meredino for the patch.

    o Reference and user manual now get rebuilt automatically when
      required.  (E.g. on 'make dist', or explicitly now through 'make
      docs'.)

    o Made it easier to change the maximum number of SSQLS data members
      in generated custom-macros.h file.  It used to be hard-coded in
      several places in lib/custom.pl; now it's a variable at the top of
      the file.

    o Changed default SSQLS data member limit to 25, which is what it
      has been documented as for a long time now.  It was actually 26
      within custom.pl.

    o Fixed a regression in previous version.

    o Trimmed some fat from the distribution packages.

    o Some more small doucmentation improvements.


1.7.33, 2005.04.29 (r555)

    o Worked around an overloaded operator lookup bug in VC++ 7.1
      that caused SSQLS insert, replace and update queries to get
      mangled.  (Symptom was that custom2 and custom3 examples didn't
      work right.)  Thanks to Mark Meredino for digging up the
      following, which explains the problem and gives the solution:

      http://groups-beta.google.com/group/microsoft.public.vc.stl/browse_thread/thread/9a68d84644e64f15

    o Some VC++ warning fixes.

    o Major documentation improvements:
    
        o Using DocBook for user manual and Doxygen for reference
          manual.  The former now references the latter where
          useful.

        o Split out HACKERS and CREDITS files from main README,
          and improved remaining bits of README.

        o Moved the text from the old v1.7.9 LaTeX-based
          documentation over into the new systems, and reworked
          it to more closely resemble English.

        o Added a lot of new material to documentation, and
          simplified a lot of what already existed.

        o Documentation is now being built in HTML and PDF forms.

    o ebuild file updated to take advantage of recent configure script
      features.  Thanks to Chris Frey for this patch.



1.7.32, 2005.03.10 (r479)

    o Example building may now be skipped with --disable-examples
      configure script flag.

    o Changed stock items added in resetdb.  One is now UTF-8 encoded,
      to show that basic use of Unicode with MySQL++ is easy, yet not
      foolproof.  (See formatting of table on systems where cout isn't
      UTF-8 aware!)  Other stock items now follow a theme, for your
      amusement.  :)

    o custom3 example now changes UTF-8 item's name to the 7-bit ASCII
      equivalent.  Previously, this example would fix a spelling error
      in the table.

    o resetdb example now says 'why' when it is unable to create the
      sample database.

    o Small formatting change to print_stock_table(), used by several
      examples.

    o Was issuing a VC++-specific warning-disable pragma when built by
      any Windows compiler.  Fixed.
    

1.7.31, 2005.03.05 (r462) The "Inevitable Point-one Followup" release

    o Check for threads support must now be explicitly requested via
      configure script's new --enable-thread-check flag.

    o Fix for contacting MySQL server on a nonstandard port number.
      Thanks to Chris Frey for this patch.

    o Example programs using standard command line format now accept a
      fourth optional parameter, a port number for the server.  Thanks
      to Chris Frey for this patch.

    o One more g++ 3.4 pedantic warning fix by Chris Frey.

    o Exception handling in resetdb is no longer nested, because you'd
      get a segfault on some systems when an exception was thrown from
      one of the inner try blocks.

    o Improvements to Connection class's handling of locking mechanism.
      Concept based on patches by Rongjun Mu.

    o Implemented the declared-but-never-defined Query::lock().  Thanks
      to Rongjun Mu for this patch.
    
    o Cleaned up some unclear if/else blocks in connection.cpp by
      adding explicit braces, correct indenting and putting normal
      code path in the if side instead of the else.


1.7.30, 2005.02.28 (r443) The "Power of Round Numbers" release

    o bootstrap script now accepts a 'pedantic' argument, which sets a
      bunch of CFLAGS that make g++ very picky about the code it
      accepts without warnings.
      
    o Fixed a bunch of things that generated warnings with g++ in
      pedantic mode. Only two warnings remain, having to do with
      floating point comparisons.  (See Wishlist for plans on how to
      deal with these.)  Thanks to Chris Frey for this patch.

    o Split long tests out of configure.in into M4 files in new config
      subdir.  This makes configure.in easier to read.

    o Added preliminary thread support.  Currently, this just means that
      we detect the required compiler and linker thread flags, and link
      against the proper thread-safe libraries.  THERE MAY BE
      UN-THREAD-SAFE CODE IN MYSQL++ STILL!

    o Standard C++ exceptions are the default now.  Old pre-Standard
      exception stuff removed.

    o Row::lookup_by_name() will throw the new BadFieldName exception if
      you pass a bad field name.  Thanks for this patch to Chris Frey.

    o Row::operator[] will throw a Standard C++ out of bounds exception
      by way of std::vector::at() if you pass it a bad index.  Thanks
      for this patch to Chris Frey.

    o Setting Connection::is_connected flag to false on close().
      Previously, is_connected() would continue to return true after
      close() was called.

    o All number-to-string conversion ctors in SQLString class now use
      ostringstream to do the conversion.  Previously, we used
      snprintf(), which isn't available on all systems.  Also, we used a
      C99 format specifier for the "long long" conversion, which is also
      not available on all systems.  This new ostringstream code should
      be platform-independent, finally.


1.7.28, 2005.02.04 (r403)

    o --with-mysql* flags to configure script now try the given
      directory explicitly, and only if that fails do they try
      variations, like tacking '/lib' and such onto it to try and find
      the MySQL includes and libraries.  Thanks to Matthew Walton for
      the patch.

    o Finally removed sql_quote.h's dependence on custom.h, by moving
      the one definition it needed from custom.h to deps.h.  This will
      help portability to compilers that can't handle the SSQLS macros,
      by making that part of the library truly optional.


1.7.27, 2005.01.12 (r395)

    o configure check for libmysqlclient now halts configuration if the
      library isn't found.  Previously, it would just be flagged as
      missing, and MySQL++ would fail to build.

    o Added sql_string.cpp to VC++ and BCBuilder project files.

    o Removed Totte Karlsson's 'populate' example, which never made it
      into the distribution anyway.

    o Removed last vestiges of 'dummy.cpp'.

    o Renamed *.cc to *.cpp in BCBuilder project files.

    o Worked around a BCBuilder C++ syntax processing bug in row.h.


1.7.26, 2004.12.17 (r382)

    o Moved all of the SQLString definitions out of the header and into
      a new .cpp file, reformatted it all, and made the integer
      conversion functions use snprintf() or _snprintf() instead of
      sprintf().  Also, widened some of the buffers for 64-bit systems.

    o Using quoted #include form for internal library headers, to avoid
      some problems with file name clashes.  (The headers should still
      be installed in their own separate directory for best results,
      however.)  Thanks to Chris Frey and Evan Wies for the patch and
      the discussion that lead to it.

    o Removed unnecessary semicolons on namespace block closures.
      Thanks to Evan Wies for this patch.

    o Fixed namespace handling in the legacy headers mysql++.hh and
      sqlplus.hh.  Thanks to Chris Frey for this patch.

    o #including iostream instead of ostream in lib/null.h for
      broader C++ compatibility.  (This may allow MySQL++ to work on GCC
      2.95.2 again, but this is unconfirmed.)

    o Detecting proper mysql_shutdown() argument handling automatically
      in platform.h for the Windows compiler case instead of making the
      user edit the file.  Thanks to Evan Wies for this patch.
    
    o Fixed examples/Makefile.simple to use new *.cpp file naming.

    o Fix to Gentoo ebuild file's exception configure switch handling.
      Thanks to Chris Frey for this patch.

    o Rebuilding lib/custom*.h intelligently now, to avoid unnecessary
      recompiles after running bootstrap script.


1.7.25, 2004.12.09 (r360)

    o Yet more fixes to the --with-mysql-lib and --with-mysql-include
      flags.

    o Added DLLEXPORT stuff to platform.h, hopefully so that someone
      can figure out how to make VC++ make a DLL version of MySQL++.

    o Renamed *.cc to *.cpp.

    o Made 'set -> myset' change in VC++ project files.

    o Some style changes (mostly whitespace) in header files.


1.7.24, 2004.12.08 (r343)

    o Fixed the --with-mysql-lib and --with-mysql-include flags'
      behavior, and extended their search ability to handle one other
      common case.  (Fixed by Steve Roberts)

    o Fixes to put freestanding functions in namespace mysqlpp.  (They
      weren't in the namespace, while all the class member functions
      were.)  This required bumping the ABI version number to 4.
      
    o Renamed set module to myset, to avoid conflicts with Standard C++
      Library's set.h when MySQL++ headers were installed into one of
      the standard system include directories.

    o Renamed all the idempotency guards to make them consistent in
      style and unique to MySQL++.

    o Reformatted all of lib/*.cc.


1.7.23, 2004.11.20 (r333)

    o Query::reset() now empties the stored query string.  If you
      subsequently stored a longer query in the object, you'd overwrite
      the previous query, but otherwise the longer part of the previous
      one would stick out past the new query.

    o We now look to the NO_LONG_LONGS macro only to decide whether to
      fake 64-bit integer support using 32-bit integers.

    o 64-bit integer support under Visual C++ may be working now, using
      that platform's __int64_t type.  This has not been tested.

    o Removed 64-bit integer support for Codewarrior on Mac OS 9 and
      earlier.  OS X uses GCC, so it requires no special support.

    o Added MinGW detection in platform.h.
    
    o If you pass a flag (-X) to the examples that take the standard
      parameters (resetdb, simple1, etc.), it prints a usage message.
    
    o Better error handling in resetdb example, where errors are the
      most critical.  (If that one runs without errors, the others
      probably will, too, and you have to run that one first.)

    o resetdb now reports success, rather than succeeding silently.

    o Removed the code in sample1 example that duplicated util module's
      print_stock_table(), and called that function instead.

    o Moved the preview() calls in the example programs to before the
      query execution calls, because execution modifies the query.

    o All examples that take the standard command line parameters now 
      exit when connect_to_db() fails in one of the ways that don't
      throw an exception, rather than bulling onward until the next
      MySQL database call fails because the connection isn't up.

    o dbinfo example now takes the standard command line parameters.

    o Much better output formatting in dbinfo example.

    o Calling reset() where appropriate in the various example programs.
      Before, the programs may have worked, but not for the right
      reason.  This lead some people to believe that calling reset()
      was not necessary.

    o Fixed an incorrect use of row["string"] in complic1 example.

    o Lots of code style improvements to the examples.

    o Some VC++ type warnings squished.  Some remain.
    

1.7.22, 2004.11.17 (r302)

    o Applied patches by Zahroof Mohammed to allow it to build under GCC
      3.4.2.  Tested on MinGW and Fedora Core 3 systems.

    o Removed all the forward declarations in defs.h, and added
      forward declarations where necessary in individual header files.
      #including defs.h in fewer locations as a result.

    o Legacy headers sqlplus.hh and mysql++.hh now declare they are
      using namespace mysqlpp, to allow old code to compile against the
      new library without changes.

    o Removed query_reset parameter from several class Query member
      functions.  In the implementation, these parameters were always
      overridden!  No sense pretending that we pay attention to these
      parameters.  This changes the ABI version to 3.

    o #including custom.h in sql_query.h again...it's necessary on GCC
      3.4.
    
    o bootstrap script runs lib/config.pl after configure.  This is
      just a nicety for those running in 'maintainer mode'.


1.7.21, 2004.11.05 (r273)

    o Generating a main mysql++ RPM containing just the library files
      and basic documentation, and the -devel package containing
      everything else.

    o Devel package contains examples now, along with a new Makefile
      that uses the system include and library files, rather than the
      automake-based Makefile.am we currently have which uses the files
      in the mysql++ source directory.

    o Renamed sqlplusint subdirectory in the package to lib.

    o Removed the obsolete lib/README file.

    o lib/sql_query.h no longer #includes custom.h, simplifying
      build-time dependencies and shortening compile times.


1.7.20, 2004.11.03 (r258)

    o Collapsed all numbered *.hh headers into a single *.h file.  For
      example, the contents of row1.hh, row2.hh and row3.hh are now in
      row.h.

    o While doing the previous change, broke several circular
      dependencies.  (The numbered file scheme was probably partly done
      to avoid this problem.)  The practical upshot of most of these
      changes is that some functions are no longer inline.

    o Removed define_short.hh and everything associated with it.  The
      library now uses the short names exclusively (e.g. Row instead of
      MysqlRow).

    o Put all definitions into namespace mysqlpp.  For most programs,
      simply adding a 'using namespace mysqlpp' near the top of the
      program will suffice to convert to this version.

    o Once again, the main include file was renamed, this time to
      mysql++.h.  Hopefully this is the last renaming!

    o mysql++.hh still exists.  It emits a compiler warning that the
      file is obsolete, then it #includes mysql++.h for you.

    o sqlplus.hh is back, being a copy of the new mysql++.hh.  Both of
      these files may go away at any time.  They exist simply to help
      people transition to the new file naming scheme.

    o Renamed mysql++-windows.hh to platform.h, and added code to it to
      handle #inclusion of config.h on autotools-based systems
      intelligently.  This fixes the config.h error when building under
      Visual C++.

    o There is now only one place where conditional inclusion of
      winsock.h happens: platform.h.

    o Beautified the example programs.


1.7.19, 2004.10.25 (r186)

    o Fixed an infinite loop in the query mechanism resulting from the
      strstream change in the previous version.  There is an overloaded
      set of str() member functions that weren't a problem when query
      objects were based on strstream.
     
    o Query mechanism had a bunch of const-incorrectness: there were
      several function parameters and functions that were const for
      the convenience of other parts of the code, but within these
      functions the constness was const_cast away!  This was evil
      and wrong; now there are fewer const promises, and only one is
      still quietly broken within the code.  (It's in the SQLQuery
      copy ctor implementation; it should be harmless.)

    o Removed operator=() in Query and SQLQuery classes.  It cannot take
      a const argument for the same reason we have to cast away const
      in the SQLQuery copy ctor.  It's tolerable to do this in the copy
      ctor, but intolerable in an operator.  Since the copy ctor is good
      enough for all code within the library and within my own code, I'm
      removing the operator.

    o Above changes required bumping the ABI to version 2.

    o Visual C++ projects now look for MySQL build files in c:\mysql,
      since that's the default install location.  (Previously, it was
      c:\program files\mysql.)


1.7.18, 2004.10.01 (r177)

    o Changed all the strstream (and friends) stuff to stringstream type
      classes.  Let there be much rejoicing.

    o Query object now lets you use store() even when the SQL query
      cannot return a result, such as a DROP TABLE command.  This is
      useful for sending arbitrary SQL to the server.  Thanks to
      Jose Mortensen for the patch.

    o Quote fix in configure.in, thanks to David Sward.

    o Renamed undef_short file to undef_short.hh.

    o Gentoo ebuild file is actually being shipped with the tarball,
      instead of just sitting in my private CVS tree since 1.7.14 was
      current.  Ooops....


1.7.17, 2004.09.16 (r170)

    o Reverted one of the VC++ warning fix changes from 1.7.16 that
      caused crashes on Linux.

    o Added a configure test that conditionally adds the extra 'level'
      parameter to mysql_shutdown() that was added in MySQL 4.1.3 and
      5.0.1.


1.7.16, 2004.09.13 (r160)

    o Building VC++ version with DLL version of C runtime libraries, and
      at warning level 3 with no warnings emitted.

    o VC++ build no longer attempts to fake "long long" support.  See
      the Wishlist for further thoughts on this.


1.7.15, 2004.09.02 (r144)

    o Renamed Configure file to common.am, to avoid file name conflict
      with configure script on case-sensitive file systems.

    o Added ebuild file and ebuild target to top-level Makefile for
      Gentoo systems.  Thanks to Chris Frey for this.

    o Small efficiency improvements to BadQuery exception handling.
      Initial idea by Chris Frey, improvements by Warren Young.


1.7.14, 2004.08.26 (r130)

    o Builds with Visual C++ 7.1.

    o Fixed a bug in custom macro generation that caused problems with
      GCC 3.4.  (X_cus_value_list ctor definition was broken.)


1.7.13, 2004.08.23 (r92)

    o Removed USL CC support.  (System V stock system compiler.)  Use
      GCC on these platforms instead.

    o Added examples/README, explaining how to use the examples, and
      what they all do.

    o Most of the example programs now accept command line arguments for
      host name, user name and password, like resetdb does.

    o Renamed sinisa_ex example to dbinfo.

    o Several Standard C++ syntax fixes to quash errors emitted by
      GCC 3.4 and Borland C++ Builder 6.  Thanks to Steffen Schumacher
      and Totte Karlsson for their testing and help with these.

    o Added proper #includes for BCBuilder, plus project files for same.
      Thanks to Totte Karlsson for these.


1.7.12, 2004.08.19 (r63)

    o Many Standard C++ fixes, most from the GCC 3.4 patch by
      Rune Kleveland.

    o Added Wishlist file to distribution.

    o Fixed a problem in the bootstrap script that caused complaints
      from the autotools on some systems.

    o RPM building is working properly now.

    o Fixed the idempotency guard in datetime1.hh.


1.7.11, 2004.08.17 (r50)

    o Renamed mysql++, defs and define_short files, adding .hh to the
      end of each.  (They're header files!)  This shouldn't impact
      library users, since these are hopefully used internal to the
      library only.

    o Removed sqlplus.hh file.  Use mysql++.hh instead.
    
    o Added mysql++.spec, extracted from contributed 1.7.9 source RPM, 
      and updated it significantly.  Also, added an 'rpm' target to
      Makefile.am to automate the process of building RPMs.

    o Added bootstrap and LGPL files to distribution tarball.

    o Added pre-1.7.10 history to this file.

    o Removed .version file.  Apparently it's something required by old
      versions of libtool.


1.7.10, 2004.08.16 (r27)

    o Maintenance taken over by Warren Young (mysqlpp at etr dash usa
      dot com.) See http://lists.mysql.com/plusplus/3326 for details.

    o Applied many of the GCC 3.x patches submitted for 1.7.9 over
      the years.  This allows it to build on everything from 3.0 to
      3.3.3, at least.  Because so many patches are rolled up in one
      big jump, it's difficult to describe all the changes and where
      they came from.  Mostly they're Standard C++ fixes, as GCC
      has become more strict in the source code that it will accept.

    o MysqlRow used to overload operator[] for string types as well as
      integers so you could look up a field by its name, rather than by
      its index.  GCC 3.3 says this is illegal C++ due to ambiguities in
      resolving which overload should be used in various situations.
      operator[] is now overloaded only for one integer type, and a
      new member function lookup_by_name() was added to maintain the old
      by-field-name functionality.

    o Fixed another operator overloading problem in SSQLS macro
      generation with GCC 3.3.

    o The _table member of SSQLS-defined structures is now const char*,
      so you can assign to it from a const char* string.

    o Got autoconf/automake build system working with current versions
      of those tools again.  Removed the generated autotools files from
      CVS.

    o Renamed library file from libsqlplus to libmysqlpp.


1.7.9 (May 1 2001) Sinisa Milivojevic <sinisa@mysql.com>

    * Fixed a serious bug in Connection constructor when reading MySQL
    * options
    * Improved copy constructor and some other methods in Result /
    * ResUse
    * Many other minor improvements
    * Produced a complete manual with chapter 5 included
    * Updated documentation, including a Postscript format

1.7.8 (November 14 2000) Sinisa Milivojevic <sinisa@mysql.com>

    * Introduced a new, standard way of dealing with C++ exceptions.
    * MySQL++ now supports two different methods of tracing exceptions.
    * One is by the fixed type (the old one) and one is standard C++
    * type by the usage of what() method. A choice of methods has to be
    * done in building a library. If configure script is run with
    * -enable-exception option , then new method will be used. If no
    * option is provided, or -disable-exception is used, old MySQL++
    * exceptions will be enforced. This innovation is a contribution of
    * Mr. Ben Johnson <ben@blarg.net>
    * MySQL++ now automatically reads at connection all standard MySQL
    * configuration files
    * Fixed a bug in sql_query::parse to enable it to parse more then 99
    * char's
    * Added an optional client flag in connect, which will enable usage
    * of this option, e.g. for getting matched and not just affected
    * rows. This change does not require any changes in existing
    * programs
    * Fixed some smaller bugs
    * Added better handling of NULL's. Programmers will get a NULL
    * string in result set and should use is_null() method in ColData to
    * check if value is NULL
    * Further improved configuration
    * Updated documentation, including a Postscript format

1.7.6 (September 22 2000) Sinisa Milivojevic <sinisa@mysql.com>

    * This release contains some C++ coherency improvements and scripts
    * enhacements
    * result_id() is made available to programmers to fetch
    * LAST_INSERT_ID() value
    * Connection constroctur ambiguity resolved, thanks to marc@mit.edu
    * Improved cnnfigure for better finding out MySQL libraries and
    * includes
    * Updated documentation, including a Postscript format

1.7.5 (July 30 2000) Sinisa Milivojevic <sinisa@mysql.com>

    * This release has mainl bug fixes  and code improvements
    * A bug in FieldNames::init has been fixed, enabling a bug free
    * usage of this class with in what ever a mixture of cases that is
    * required
    * Changed behaviour of ResUse, Result and Row classes, so that they
    * could be re-used as much as necessary, without any memory leaks,
    * nor with any re-initializations necessary
    * Fixed all potential leaks that could have been caused by usage of
    * delete instead of delete[] after memory has been allocated with
    * new[]
    * Deleted all unused classes and macros. This led to a reduction of
    * library size to one half of the original size. This has
    * furthermore brought improvements in compilation speed
    * Moved all string manipulation from system libraries to
    * libmysqlclient, thus enabling uniformity of code and usage of 64
    * bit integers on all platforms, including Windows, without
    * reverting to conditional compilation. This changes now requires
    * usage of mysql 3.23 client libraries, as mandatory
    * Changed examples to reflect above changes
    * Configuration scripts have been largely changed and further
    * changes shall appear in consecutive sub-releases. This changes
    * have been done and shall be done by our MySQL developer Thimble
    * Smith <tim@mysql.com>
    * Changed README, TODO and text version of manual. Other versions of
    * manual have not been updated
    * Fixed .version ``bug''. This is only partially fixed and version
    * remains 1.7.0 due to some problems in current versions of libtool.
    * This shall be finally fixed in a near future
    * Several smaller fixes and improvements
    * Added build.sh script to point to the correct procedure of
    * building of this library. Edit it to add configure options of your
    * choice

1.7 (May17 2000) Sinisa Milivojevic <sinisa@mysql.com>

    * This is mainly a release dealing with bug fixes, consistency
    * improvements and easier configure on some platforms
    * A bug in fetch_row() method of ResUse class has been fixed. Beside
    * changes that existed in a distributed patch, some additional error
    * checking has been introduced
    * A bug in escape manipulator has been fixed that could cause an
    * error if all characters had to be escaped
    * An inconsistency in column indexing has been fixed. Before this
    * version, column names in row indexing with strings, i.e.
    * row[<string>] , has been case sensitive, which was inconsistent
    * with MySQL server handling of column names
    * An inconsistency in conversion from strings to integers or floats
    * has been fixed. In prior version a space found in data would cause
    * a BadConversion exception. This has been fixed, but 100%
    * consistency with MySQL server has not been targeted, so that other
    * non-numeric characters in data will still cause BadConversion
    * exception or error. As this API is used in applications, users
    * should provide feedback if full compatibility with MySQL server is
    * desired, in which case BadConversion exception or error would be
    * abolished in some of future versions
    * A new method in ColData class has been introduced. is_null()
    * method returns a boolean to denote if a column in a row is NULL.
    * Finally, as of this release, testing for NULL values is possible.
    * Those are columns with empty strings for which is_null() returns
    * true.
    * Some SPARC Solaris installations had C++ exception problems with
    * g++ 2.95.2 This was a bug that was fixed in GNU gcc, as from
    * release 2.95 19990728. This version was thoroughly tested and is
    * fully functional on SPARC Solaris 2.6 with the above version of
    * gcc.
    * A 'virtual destructor ' warning for Result class has been fixed
    * Several new functions for STL strings have been added. Those
    * functions (see string_util.hh) add some of the functionality
    * missing in existing STL libraries
    * Conversion for 64 bit integers on FreeBSD systems has been added.
    * On those systems _FIX_FOR_BSD_ should be defined in CXXFLAGS prior
    * to configuring. Complete conversion to the usage of functions for
    * integer conversion found in mysqlclient library is planned for one
    * of the next releases
    * A completely new, fully dynamic, dramatic and fully mutable result
    * set has been designed and will be implemented in some of 2.x
    * releases
    * Several smaller fixes and improvements, including defaulting
    * exceptions to true, instead of false, as of this version
    * An up-to-date and complete Postscript version of documentation is
    * included in this distribution
    * Large chunks of this manual are changed, as well as README and
    * TODO files.

1.6 (Feb 3 2000) Sinisa Milivojevic <sinisa@mysql.com>

    * This is a major release as it includes new features and major
    * rewrites
    * Automatic quoting and escaping with streams. It works
    * automatically , depending on the column type. It will work with <<
    * on all ostream derived types. it is paricularly handy with query
    * objects and strstreams. Automatic quoting and escaping on cout,
    * cerr and clog stream objects is intentionally left out, as quoting
    * / escaping on those stream objects is not necessary. This feature
    * can be turned of by setting global boolean dont_quote_auto to
    * true.
    * Made some major changes in code, so that now execute method should
    * be used only with SSQL and template queries, while for all other
    * query execution of UPDATE's, INSERT's, DELETE's, new method exec()
    * should be used. It is also faster.
    * New method get_string is inroduced for easier handling / casting
    * ColData into C++ strings.
    * Major rewrite of entire code, which led to it's reduction and
    * speed improvement. This also led to removal of several source
    * files.
    * Handling of binary data is introduced. No application program
    * changes are required. One of new example programs demonstrates
    * handling of binary data
    * Three new example programs have been written and thoroughly
    * tested. Their intention is to solve some problems addressed by
    * MySQL users.
    * Thorough changes is Makefile system has been made
    * Better configuration scripts are written, thanks to D.Hawkins
    * <dhawkins@cdrgts.com>
    * Added several bug fixes
    * Changed Manual and Changelog

1.5 (Dec 1 1999) Sinisa Milivojevic <sinisa@mysql.com>

    * Fixed bug in template queries, introduced in 1.4 (!)
    * Fixed connect bug
    * Fixed several bug in type_info classes
    * Added additional robustness in classes
    * Added additional methods for SQL type info
    * Changed Changelog and README

1.4 (Nov 25 1999) Sinisa Milivojevic <sinisa@mysql.com>

    * Fixed bug in store and storein methods
    * Fixed one serious memory leak
    * Fixed a very serious bug generated by gcc 2.95.xx !!
    * Added robustness in classes, so that e.g. same query and row
    * objects can be re-used
    * Changed sinisa_ex example to reflect and demonstrate this
    * stability
    * Changed Changelog and README
    * Few other bug fixes and small improvements and speed-ups

1.3 (Nov 10 1999) Sinisa Milivojevic <sinisa@mysql.com>

    * Fixed several erronous definitions
    * Further changed source to be 2.95.2 compatible
    * Expunged unused statements, especially dubious ones, like use of
    * pointer_tracker
    * Corrected bug in example file fieldinf1
    * Finally fixed mysql_init in Connection constructor, which provided
    * much greater stability !
    * Added read and get options, so that clients, like mysqlgui can use
    * it
    * Changed Changelog and README
    * Many other bug fixes.

1.2 (Oct 15 1999) Sinisa Milivojevic <sinisa@mysql.com>

    * First offical release. Version 1.0 and 1.1 were releases by Sinisa
    * before I (Kevin Atkinson) made him the offical maintainer,
    * Many manual fixes.
    * Changed README and Changelog
    * Changed source to be compilable by gcc 2.95.xx, tribute to Kevin
    * Atkinson <kevinatk@home.com>
    * Added methods in Connection class which are necessary for
    * fullfilling administrative functions with MySQL
    * Added many bug fixes in code pertaining to missing class
    * initializers , as notified by Michael Rendell <michael@cs.mun.ca>
    * Sinisa Milivojevic <sinisa@mysql.com> is now the offical
    * maintainer.

1.1 (Aug 2 1999) Sinisa Milivojevic <sinisa@mysql.com>

    * Added several bug fixes
    * Fixed memory leak problems and variables overlapping problems.
    * Added automake and autoconf support by loic@ceic.com
    * Added Makefile for manual
    * Added support for cygwin
    * Added example sinisa_ex (let modesty prevail) which used to crash
    * a lot when memory allocation, memory leak and overlap problems
    * were present. Smooth running of this example proves that all those
    * bugs are fixed
    * Corrected bugs in sql_query.cc regarding delete versus delete[]
    * and string length in manip.cc
    * Changed manual
    * Changed README
    * Many other smaller things

1.0 (June 9 1999) Michael Widenius <monty@monty.pp.sci.fi>

    * Added patches from Orion Poplawski <orion@bvt.com> to support the
    * UnixWare 7.0 compiler

.64.1.1a (Sep 27 1998)

    * Fixed several bugs that caused my library to fail to compile with
    * egcs 1.1. Hopefully it will still compile with egcs 1.0 however I
    * have not been able to test it with egcs 1.0.
    * Removed some problem causing debug output in sql++pretty.

.64.1a (Aug 1 1998)

    * Added an (almost) full guide to using Template Queries.
    * Fixed it so the SQLQuery will throw an exception when all the
    * template parameters are not provided.
    * Proofread and speedchecked the manual (it really needed it).
    * Other minor document fixes.

.64.0.1a (July 31 1998)

    * Reworked the Class Reference section a bit.
    * Minor document fixes
    * Added more examples for SSQLS.
    * Changed the syntax of equal_list for SSQLS from equal_list (cchar
    * *, Manip, cchar *) to (cchar *, cchar *, Manip).
    * Added set methods to SSQLS. These new methods do the same thing as
    * there corresponding constructors.
    * Added methods for creating a mysql_type_info from a C++ type_info.

.64.a (July 24 1998)

    * Changed the names of all the classes so they no longer have to
    * have Mysql in the begging of it. However if this creates a problem
    * you can define a macro to only use the old names instead.
    * The Specialized SQL Structures (formally known as Custom Mysql
    * Structures) changed from mysql_ to sql_.
    * Added the option of using exceptions thoughout the API.
    * ColData (formally known as MysqlStrings) will now throw an
    * exception if there is a problem in the conversion.
    * Added a null adapter.
    * Added Mutable Result Sets
    * Added a very basic runtime type identification for SQL types
    * Changed the document format from POD to LYX .
    * Am now using a modified version of Perceps to extract the class
    * information directly from the code to make my life easier.
    * Added an option of defining a macro to avoid using the automatic
    * conversion with binary operators.
    * Other small fixed I probully forgot to mentune.

.63.1.a

    * Added Custom Mysql Structures.
    * Fixed the Copy constructor of class Mysql
    * Started adding code so that class Mysql lets it children now when
    * it is leaving
    * Attempted to compile it into a library but still need help. As
    * default it will compile as a regular program.
    * Other small fixes.

.62.a (May 3 1998)

    * Added Template Queries
    * Created s separate SQLQuery object that is independent of an SQL
    * connection.
    * You no longer have to import the data for the test program as the
    * program creates the database and tables it needs.
    * Many small bug fixes.

.61.1.a (April 28 1998)

    * Cleaned up the example code in test.cc and included it in the
    * manual.
    * Added an interface layout plan to the manual.
    * Added a reverse iterator.
    * Fixed a bug with row.hh (It wasn't being included because of a
    * typo).

.61.0.a

    * Major interface changes. I warned you that the interface may
    * change while it is in pre-alpha state and I wasn't kidding.
    * Created a new and Separate Query Object. You can no longer execute
    * queries from the Mysql object instead you have to create a query
    * object with Mysql::query() and use it to execute queries.
    * Added the comparison operators to MysqlDate, MysqlTime and
    * MysqlDateTime. Fixed a few bugs in the MysqlDate... that effected
    * the stream output and the conversion of them to strings.
    * Reflected the MysqlDate... changes in the manual.
    * Added a new MysqlSet object and a bunch of functions for working
    * with mysql set strings.

.60.3a (April 24 1998)

    * Changed strtoq and strtouq to strtoll and strtull for metter
    * compatibility Minor Manual fix.
    * Changed makefile to make it more compatible with Solaris (Thanks
    * Chris H)
    * Fixed bug in comparison functions so that they would compare in he
    * right direction.
    * Added some items to the to do list be sure to have a look.

Changes to examples/vstudio/mfc/mfc.h.



1
2





3
4



5


6

7





8






9


10




11

12




13

14





15




16

17
18
19







20


21



22


23
24



25


26



27





28




29





30




31

32

33



34

















/***********************************************************************
 mfc.cpp - Declares the MFC application object.  Nothing interesting to





	see here.  Move along to mfc_dlg.cpp, folks.




 Copyright (c) 2007 by Educational Technology Resources, Inc.  Others 


 may also hold copyrights on code in this file.  See the CREDITS.txt

 file in the top directory of the distribution for details.












 This file is part of MySQL++.







 MySQL++ is free software; you can redistribute it and/or modify it

 under the terms of the GNU Lesser General Public License as published




 by the Free Software Foundation; either version 2.1 of the License, or

 (at your option) any later version.










 MySQL++ is distributed in the hope that it will be useful, but WITHOUT

 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
 License for more details.










 You should have received a copy of the GNU Lesser General Public



 License along with MySQL++; if not, write to the Free Software


 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
 USA



***********************************************************************/






#pragma once










class CApp : public CWinApp





{




public:

	CApp() { }

	virtual BOOL InitInstance();



};















>
>
|
|
>
>
>
>
>
|

>
>
>
|
>
>
|
>
|
>
>
>
>
>

>
>
>
>
>
>
|
>
>

>
>
>
>
|
>
|
>
>
>
>
|
>
|
>
>
>
>
>

>
>
>
>
|
>
|
|
|
>
>
>
>
>
>
>

>
>
|
>
>
>
|
>
>
|
|
>
>
>
|
>
>

>
>
>
|
>
>
>
>
>

>
>
>
>
|
>
>
>
>
>
|
>
>
>
>
|
>
|
>
|
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
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
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
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
Patches for any of these thoughtfully considered!  See the HACKERS.txt
file for instructions on sending patches.


Any Version
-----------
    o Any time you must hand-roll some SQL code in your program,
      consider whether it could be generalized to a widely-useful
      API feature.


v3.1 Tentative Plan
-------------------
    o SSQLS v2:

      - Switch from C macros to a DSL that is translated to .cpp and
        .h files by a tool built along with MySQL++ library.  Design:

        http://lists.mysql.com/plusplus/6929

      - Switch per SSQLS that makes it throw an exception when it sees
        a mismatch between DB schema and SSQLS definition.  Harkens
        back to pre v3.0 SSQLS behavior, where you'd get a crash as
        it tried to fill out fields by position, and fail.  For the
        B&D folk who don't like the new "just cope" behavior.

      - Try to design it so as much code as possible resides in
        a common base class (SsqlsBase) that all SSQLSes derive from.
        Can't do it in v1 because virtually everything is specific
        to the structure's type.  Study equal_list(), for example.
        Do it with an eye toward replacing Query's template methods
        taking SSQLSes with concrete methods taking SsqlsBase&.

      - Add truthiness operator to SSQLS to detect an incompletely-
        populated object?  Or maybe an incomplete() method?

      - Add features to ssqlsxlat to write SSQLSv2 declaration files
        from existing schemas extracted from CREATE TABLE statements,
        from running databases, and from C++ files containing old
        SSQLS v1 declarations.

      - Add table creation ability to SSQLS.  It has the schema...

      - Support per-instance table name overrides, instead of just
        per SSQLS?  Needed if you're going to use a single SSQLS for
        many tables with the same structure in a multithreaded program,
        so changing it statically isn't safe.

    o Chris Frey's packarray class

    o Create adaptors for std::bitset, for storing binary data in a
      MySQL table.  Make two options available, one for storing the
      return from bitset::to_ulong() in an UNSIGNED INTEGER column,
      and another for storing a larger set of bits in a more flexible
      way, perhaps as a BLOB.

    o field_list should use backticks to quote its items to handle
      spaces and other special characters.  Probably also remove all
      the manipulator stuff associated with these: no reason to make
      it user-settable, as there's only one right way to do it.  See:

         http://dev.mysql.com/doc/refman/5.0/en/identifiers.html

    o Add a general-purpose backtick manipulator as well.

    o Define operator<< for Fields, Row, StoreQueryResult, etc.  In other
      words, there should be a way to get a user-readable version of
      received data without a lot of code.  CSV format by default, and
      mysql(1)-like ASCII grid optionally, perhaps with a manipulator?
      There is grid code in examples/multiquery.cpp which we can use
      and then make multiquery.cpp a demonstration platform for it.
      Maybe dbinfo and fieldinf, too?

    o Has experience with new thread awareness changed our mind on
      atomic inc/dec of reference counts in RefCounted*?

    o Create a fixed-point data type for use with SQL's DECIMAL and
      related types.  Right now, sql_decimal is a typedef for double,
      so you lose accuracy in the fractional part.

    o Optional checked conversions in String for numerics: throw
      BadConversion on range overflow?


v4.0 or Later
-------------
    o Database independence:

      - Make DBDriver class purely abstract; move its entire functional
        contents to new MysqlDriver.

      - Must create at least two other DBDriver subclasses to
        ensure base class is reusable before releasing v4.0.
        PostgresDriver and SqlLiteDriver?

      - Templatize all classes that use DBDriver interface with the
        DB driver type.  This lets you specify the driver type to use
        with a Connection and all its children without modifying the
        existing method parameter lists.  This also lets us worry less
        about C API types, as they can be hidden away behind typedefs:

        class MysqlDriver : public DBDriver { ...
           typedef MYSQL_ROW row_type;
           ...
        }

        template <class DBD = MysqlDriver>
        class Connection ... { ...
           Query<DBD> query();
           ...
        }

        template <class DBD = MysqlDriver>
        class UseQueryResult { ...
            DBD::row_type fetch_raw_row();
        }

      - Tricky bits:
    
        - Initializing result set objects.

        - type_info module.  Extremely closely tied to MySQL C API
          right now.  Will probably have to turn it into a parallel
          class hierarchy to DBDriver, or fold it in with same.

        - Building MySQL++ on systems without autoconf.  How to
          specify what DB engines are available?  Probably default to
          supporting MySQL only, and let people turn things on manually
          as they need them.  Or, maybe make them use Bakefile so they
          can fiddle with the options if they want something atypical.

    o Some sort of support for prepared statements.  Can we hijack
      the template query mechanism?

    o If SSQLSv2 does use a common base class, change Query template
      methods taking SSQLS into concrete methods taking SsqlsBase&.

    o Make Query::insert(), replace() and update() execute their
      queries immediately.  Requires an ABI break, because they'll
      have to return SimpleResult.

Changes to examples/vstudio/mfc/mfc.rc.

1

2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
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
56
57
58
59
60
61
62


63
64
65




66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81





82
83
84
85
86


87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130

131
132





133








134












































































































































































































































































































135
// Microsoft Visual C++ generated resource script.

//
#include "resource.h"

#define APSTUDIO_READONLY_SYMBOLS
/////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 2 resource.
//
#include "afxres.h"

/////////////////////////////////////////////////////////////////////////////
#undef APSTUDIO_READONLY_SYMBOLS

/////////////////////////////////////////////////////////////////////////////
// English (U.S.) resources

#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
#ifdef _WIN32
LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
#pragma code_page(1252)
#endif //_WIN32

#ifdef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// TEXTINCLUDE
//

1 TEXTINCLUDE 
BEGIN
    "resource.h\0"


END

2 TEXTINCLUDE 
BEGIN
    "#include ""afxres.h""\r\n"
    "\0"
END

3 TEXTINCLUDE 
BEGIN
    "#define _AFX_NO_SPLITTER_RESOURCES\r\n"
    "#define _AFX_NO_OLE_RESOURCES\r\n"
    "#define _AFX_NO_TRACKER_RESOURCES\r\n"
    "#define _AFX_NO_PROPERTY_RESOURCES\r\n"
    "\r\n"
    "#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)\r\n"
    "LANGUAGE 9, 1\r\n"
    "#pragma code_page(1252)\r\n"
    "#include ""afxres.rc""     // Standard components\r\n"
    "#endif\r\n"
    "\0"
END

#endif    // APSTUDIO_INVOKED


/////////////////////////////////////////////////////////////////////////////
//
// Dialog
//



IDD_MFC_DIALOG DIALOGEX 0, 0, 210, 105
STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_VISIBLE | WS_CAPTION




EXSTYLE WS_EX_APPWINDOW
CAPTION "MySQL++ MFC Example"
FONT 8, "MS Shell Dlg", 0, 0, 0x1
BEGIN
    EDITTEXT        IDC_SERVER_EDIT,51,7,94,14,ES_AUTOHSCROLL
    EDITTEXT        IDC_USER_EDIT,51,24,94,14,ES_AUTOHSCROLL
    EDITTEXT        IDC_PASSWORD_EDIT,51,41,94,14,ES_PASSWORD | ES_AUTOHSCROLL
    DEFPUSHBUTTON   "Connect!",IDC_CONNECT_BUTTON,153,7,50,14
    PUSHBUTTON      "Close",IDCANCEL,153,25,50,16
    LISTBOX         IDC_RESULTS_LIST,51,58,94,40,LBS_SORT | LBS_NOINTEGRALHEIGHT | WS_DISABLED | WS_VSCROLL
    RTEXT           "Server:",IDC_STATIC,7,7,40,8
    RTEXT           "User name:",IDC_STATIC,7,24,40,8
    RTEXT           "Password:",IDC_STATIC,7,41,40,8
    RTEXT           "Results:",IDC_STATIC,7,58,40,8
END







/////////////////////////////////////////////////////////////////////////////
//
// DESIGNINFO
//



#ifdef APSTUDIO_INVOKED
GUIDELINES DESIGNINFO 
BEGIN
    IDD_MFC_DIALOG, DIALOG
    BEGIN
        LEFTMARGIN, 7
        RIGHTMARGIN, 203
        TOPMARGIN, 7
        BOTTOMMARGIN, 98
    END
END
#endif    // APSTUDIO_INVOKED


/////////////////////////////////////////////////////////////////////////////
//
// String Table
//

STRINGTABLE 
BEGIN
    IDP_SOCKETS_INIT_FAILED "Windows sockets initialization failed."
END

#endif    // English (U.S.) resources
/////////////////////////////////////////////////////////////////////////////



#ifndef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 3 resource.
//
#define _AFX_NO_SPLITTER_RESOURCES
#define _AFX_NO_OLE_RESOURCES
#define _AFX_NO_TRACKER_RESOURCES
#define _AFX_NO_PROPERTY_RESOURCES

#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
LANGUAGE 9, 1
#pragma code_page(1252)
#include "afxres.rc"     // Standard components

#endif






/////////////////////////////////////////////////////////////////////////////








#endif    // not APSTUDIO_INVOKED













































































































































































































































































































|
>
|
<
|
|
|
|
<
<
<
|
<
<
|
<
<

<
<
<
<
<
|
<
<
<
<
<
|
<
<
|
>
>
<

<
<
<
<
<
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<

<
|
|
<
<
<
<
>
>

<
<
>
>
>
>
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<

>
>
>
>
>

<
<
<
<
>
>

|
<
<
<
<
<
<
<
<
<
<
<

|
<
<
|
<

<
<
<
<
|
<
<

|

|
<
|
<
<
<
<
<
<
|
<
<
<
<
>


>
>
>
>
>
|
>
>
>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

1
2
3

4
5
6
7



8


9


10





11





12


13
14
15

16





17














18

19
20




21
22
23


24
25
26
27















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
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
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
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
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
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
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
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
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
/// \file connection.h
/// \brief Declares the Connection class.
///

/// Every program using MySQL++ must create a Connection object, which
/// manages information about the connection to the database server, and
/// performs connection-related operations once the connection is up.
/// Subordinate classes, such as Query and Row take their defaults as



/// to whether exceptions are thrown when errors are encountered from


/// the Connection object that created them, directly or indirectly.








/***********************************************************************





 Copyright (c) 1998 by Kevin Atkinson, (c) 1999-2001 by MySQL AB, and


 (c) 2004-2007 by Educational Technology Resources, Inc.  Others may
 also hold copyrights on code in this file.  See the CREDITS file in
 the top directory of the distribution for details.







 This file is part of MySQL++.
















 MySQL++ is free software; you can redistribute it and/or modify it
 under the terms of the GNU Lesser General Public License as published




 by the Free Software Foundation; either version 2.1 of the License, or
 (at your option) any later version.



 MySQL++ is distributed in the hope that it will be useful, but WITHOUT
 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
 License for more details.
















 You should have received a copy of the GNU Lesser General Public
 License along with MySQL++; if not, write to the Free Software
 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
 USA
***********************************************************************/





#if !defined(MYSQLPP_CONNECTION_H)
#define MYSQLPP_CONNECTION_H

#include "common.h"












#include "noexceptions.h"


#include "options.h"






#include <string>



namespace mysqlpp {

#if !defined(DOXYGEN_IGNORE)

// Make Doxygen ignore this






class MYSQLPP_EXPORT Query;




class DBDriver;
#endif

/// \brief Manages the connection to the database server.
///
/// This class is a thick wrapper around DBDriver, adding high-level
/// error handling, utility functions, and abstraction away from
/// underlying C API details.

class MYSQLPP_EXPORT Connection : public OptionalExceptions
{
private:
	/// \brief Pointer to bool data member, for use by safe bool
	/// conversion operator.
	///
	/// \see http://www.artima.com/cppsource/safebool.html
    typedef bool Connection::*private_bool_type;

public:
	/// \brief Create object without connecting to the database server.
	///
	/// \param te if true, exceptions are thrown on errors
	Connection(bool te = true);

	/// \brief Create object and connect to database server in one step.
	///
	/// This constructor allows you to most fully specify the options
	/// used when connecting to the database server.
	///
	/// \param db name of database to select upon connection
	/// \param server specifies the IPC method and parameters for
	///     contacting the server; see below for details
	/// \param user user name to log in under, or 0 to use the user
	///		name this program is running under
	/// \param password password to use when logging in
	/// \param port TCP port number database server is listening on, or
	///		0 to use default value; note that you may also give this as
	///     part of the \c server parameter
	///
	/// The server parameter can be any of several different forms:
	///
	/// - \b 0: Let the database driver decide how to connect; usually
	///   some sort of localhost IPC method.
	/// - \b ".": On Windows, this means named pipes, if the server
	///   supports it
	/// - \b "/some/domain/socket/path": If the passed string doesn't
	///   match one of the previous alternatives and we're on a system
	///   that supports Unix domain sockets, MySQL++ will test it to see
	///   if it names one, and use it if we have permission.
	/// - \b "host.name.or.ip:port": If the previous test fails, or if
	///   the system doesn't support Unix domain sockets at all, it
	///   assumes the string is some kind of network address, optionally
	///   followed by a colon and port.  The name can be in dotted quad
	///   form, a host name, or a domain name.  The port can either be a
	///   TCP/IP port number or a symbolic service name.  If a port or
	///   service name is given here and a nonzero value is passed for
	///   the \c port parameter, the latter takes precedence.
	Connection(const char* db, const char* server = 0, const char* user = 0,
			const char* password = 0, unsigned int port = 0);

	/// \brief Establish a new connection using the same parameters as
	/// an existing connection.
	///
	/// \param other existing Connection object
	Connection(const Connection& other);

	/// \brief Destroy object
	virtual ~Connection();

	/// \brief Get version of library underpinning the current database
	/// driver.
	std::string client_version() const;

	/// \brief Connect to database after object is created.
	///
	/// It's better to use the connect-on-create constructor if you can.
	/// See its documentation for the meaning of these parameters.
	///
	/// If you call this method on an object that is already connected
	/// to a database server, the previous connection is dropped and a
	/// new connection is established.
	virtual bool connect(const char* db = 0, const char* server = 0,
			const char* user = 0, const char* password = 0,
			unsigned int port = 0);

	/// \brief Returns true if connection was established successfully
	///
	/// \return true if connection was established successfully
	bool connected() const;

	/// \brief Returns the number of rows in a table
	///
	/// \param table name of table whose rows you want counted
	///
	/// This is syntactic sugar for a \c SELECT \c COUNT(*)
	/// \c FROM \c table SQL query.
	ulonglong count_rows(const std::string& table);

	/// \brief Ask the database server to create a database
	///
	/// \param db name of database to create
	///
	/// \return true if database was created successfully
	bool create_db(const std::string& db);

	/// \brief Drop the connection to the database server
	void disconnect();

	/// \brief Returns a reference to the current database driver
	///
	/// \internal This exists mostly for the benefit of Query, Result
	/// and ResUse.  If there is something you want to use in the
	/// DBDriver interface, look for something similar in one of these
	/// classes instead.  If you still can't find it, send a message to
	/// the mailing list asking about it.  Unless you're doing something
	/// very low-level, there should never be a reason to use the 
	/// driver directly.
	DBDriver* driver() { return driver_; }

	/// \brief Asks the database server to drop (destroy) a database
	///
	/// \param db name of database to destroy
	///
	/// \return true if database was dropped successfully
	bool drop_db(const std::string& db);

	/// \brief Return last error number associated with this
	/// connection
	int errnum();

	/// \brief Return error message for last error associated with
	/// this connection.
	///
	/// Returns either a MySQL++-specific error message if one exists,
	/// or one from the current database driver otherwise.
	const char* error() const;

	/// \brief Get information about the IPC connection to the
	/// database server
	///
	/// String contains info about type of connection (e.g. TCP/IP,
	/// named pipe, Unix socket...) and the server hostname.
	std::string ipc_info() const;

	/// \brief Kill a database server thread
	///
	/// \param tid ID of thread to kill
    ///
    /// \see thread_id()
	bool kill(unsigned long tid) const;

	/// \brief Test whether any error has occurred within the object.
	///
	/// Allows the object to be used in bool context, like this:
	///
	/// \code
	///	Connection conn;
	///	.... use conn
	///	if (conn) {
	///	    ... nothing bad has happened since last successful use
	///	}
	///	else {
	///	    ... some error has occurred
	///	}
	/// \endcode
	///
	/// Prior to MySQL++ v3, the object was always falsy when we
	/// weren't connected.  Now a true return simply indicates a lack of
	/// errors.  If you've been using this to test for whether the
	/// connection is still up, you need to call connected() instead.
	operator private_bool_type() const
	{
		return copacetic_ ? &Connection::copacetic_ : 0;
	}

	/// \brief Copy an existing Connection object's state into this
	/// object.
	Connection& operator=(const Connection& rhs);

	/// \brief "Pings" the database server
	///
	/// \retval true if server is responding
	/// \retval false if either we already know the connection is down
	/// and cannot re-establish it, or if the server did not respond to
	/// the ping and we could not re-establish the connection.
	bool ping();

	/// \brief Returns version number of the protocol the database
	/// driver uses to communicate with the server.
	int protocol_version() const;

	/// \brief Return a new query object.
	///
	/// The returned query object is tied to this connection object,
	/// so when you call a method like
	/// \link Query::execute() execute() \endlink
	/// on that object, the query is sent to the server this object
	/// is connected to.
	///
	/// \param qstr an optional query string for populating the
	/// new Query object
	Query query(const char* qstr = 0);

	/// \brief Return a new query object
	///
	/// \param qstr initial query string
	Query query(const std::string& qstr);

	/// \brief Change to a different database managed by the
	/// database server we are connected to.
	///
	/// \param db database to switch to
	///
	/// \retval true if we changed databases successfully
	bool select_db(const std::string& db);

	/// \brief Get the database server's version string
	std::string server_version() const;

	/// \brief Sets a connection option
	///
	/// \param o pointer to any derivative of Option allocated on
	/// the heap
	///
	/// Objects passed to this method and successfully set will be
	/// released when this Connection object is destroyed.  If an error
	/// occurs while setting the option the object will be deleted
	/// immediately.
	///
	/// Because there are so many Option subclasses, the actual effect
	/// of this function has a wide range.  This mechanism abstracts
	/// away many things that are unrelated down at the database driver
	/// level, hiding them behind a coherent, type-safe interface.
	///
	/// The rules about which options can be set, when, are up to the
	/// underlying database driver.  Some must be set before the
	/// connection is established because they can only be used during
	/// that connection setup process.  Others can be set at any time
	/// after the connection comes up.  If you get it wrong, you'll get
	/// a BadOption exception.
	///
	/// \retval true if option was successfully set
	bool set_option(Option* o);

	/// \brief Ask database server to shut down.
	bool shutdown();

	/// \brief Returns information about database server's status
	std::string server_status() const;

	/// \brief Returns true if both MySQL++ and database driver we're
	/// using were compiled with thread awareness.
	bool thread_aware() const;

	/// \brief Tells the underlying database driver that this thread
	/// is done using the library.
	void thread_end();

	/// \brief Returns the database server's thread ID for this connection
	///
	/// This has nothing to do with threading on the client side.  The
	/// only thing you can do with this value is pass it to kill().
	unsigned long thread_id();

	/// \brief Tells the underlying database driver that the current
	/// thread is now using its services.
	///
	/// It's not necessary to call this from the thread that creates
	/// the connection as it's done automatically.  This method exists
	/// for times when multiple threads may use this object; it allows
	/// the underlying database driver to set up any per-thread data
	/// structures it needs.
	///
	/// The MySQL++ user manual's <a href="../userman/threads.html">chapter
	/// on threads</a> details two major strategies for dealing with
	/// connections in the face of threads.  The Connection-per-thread
	/// option frees you from ever having to call this method.  The
	/// other documented strategy is to use ConnectionPool, which opens
	/// the possibility for one thread to create a connection that
	/// another uses, so you do need to call this method in that case,
	/// or with any other similar strategy.
	///
	/// \retval True if there was no problem
	bool thread_start();

protected:
	/// \brief Build an error message in the standard form used whenever
	/// one of the methods can't succeed because we're not connected to
	/// the database server.
	void build_error_message(const char* core);

	/// \brief Establish a new connection as a copy of an existing one
	///
	/// \param other the connection to copy
	void copy(const Connection& other);

	/// \brief Extract elements from the server parameter in formats
	/// suitable for passing to DBDriver::connect().
	bool parse_ipc_method(const char* server, std::string& host,
			unsigned int& port, std::string& socket_name);

	//// Subclass data
	mutable std::string error_message_;	///< MySQL++ specific error, if any

private:
	DBDriver* driver_;
	bool copacetic_;
};


} // end namespace mysqlpp

// Not strictly required, but bring in our specialization subclasses
#include "tcp_connection.h"
#include "uds_connection.h"
#include "wnp_connection.h"

#endif // !defined(MYSQLPP_CONNECTION_H)

Changes to examples/vstudio/mfc/mfc_dlg.cpp.

1
2
3
4

5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
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
56
57
58
59

60
61
62

63
64

65
66
67
68
69
70
71

72
73
74

75
76
77


78

79
80
81
82

83
84
85

86
87
88


89
90
91
92
93
94
95


96
97
98
99
100
101


102
103
104
105

106
107
108
109
110
111
112
113
114
115
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
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
191
192
193
194




195
196
197
198
199
200
201
202

203
204
205
206
207
208
209

210
211
212
213









214


215



216
217


218
219
220


221
222
223
224



225
226
227
228
229

230

231
232
233

234
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







269
270
271
272
273

274
/***********************************************************************
 mfc_dlg.cpp - Defines the dialog box behavior for the MySQL++ MFC
	example.


 Copyright (c) 2007 by Educational Technology Resources, Inc.  Others 
 may also hold copyrights on code in this file.  See the CREDITS.txt
 file in the top directory of the distribution for details.

 This file is part of MySQL++.

 MySQL++ is free software; you can redistribute it and/or modify it
 under the terms of the GNU Lesser General Public License as published
 by the Free Software Foundation; either version 2.1 of the License, or
 (at your option) any later version.

 MySQL++ is distributed in the hope that it will be useful, but WITHOUT
 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
 License for more details.

 You should have received a copy of the GNU Lesser General Public
 License along with MySQL++; if not, write to the Free Software
 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
 USA
***********************************************************************/

#include "stdafx.h"
#include "mfc_dlg.h"

#include <mysql++.h>

BEGIN_MESSAGE_MAP(CExampleDlg, CDialog)
	ON_BN_CLICKED(IDC_CONNECT_BUTTON, &CExampleDlg::OnBnClickedConnectButton)
END_MESSAGE_MAP()


//// ctor //////////////////////////////////////////////////////////////

CExampleDlg::CExampleDlg(CWnd* pParent) :
CDialog(IDD_MFC_DIALOG, pParent)
{
	LoadDefaults();
}


//// AddMessage ////////////////////////////////////////////////////////
// Inserts the given string at the end of the list box we're using for
// output to the user.

void 
CExampleDlg::AddMessage(LPCTSTR pcMessage)
{
	ResultsList.InsertString(-1, pcMessage);
}


//// DoDataExchange ////////////////////////////////////////////////////
// Transfer data from the controls into our member variables


void
CExampleDlg::DoDataExchange(CDataExchange* pDX)
{

	CDialog::DoDataExchange(pDX);
	DDX_Text(pDX, IDC_SERVER_EDIT, sServerAddress);

	DDX_Text(pDX, IDC_USER_EDIT, sUserName);
	DDX_Text(pDX, IDC_PASSWORD_EDIT, sPassword);
	DDX_Control(pDX, IDC_RESULTS_LIST, ResultsList);
}


//// LoadDefaults //////////////////////////////////////////////////////

// Load default input values from registry, if they exist.

void

CExampleDlg::LoadDefaults()
{
	HKEY key = OpenSettingsRegistryKey();


	if (key) {

		TCHAR acSetting[100];
		if (LoadSetting(key, _T("user"), acSetting, sizeof(acSetting))) {
			sUserName = acSetting;
		}

		if (LoadSetting(key, _T("server"), acSetting, sizeof(acSetting))) {
			sServerAddress = acSetting;
		}

		RegCloseKey(key);
	}



	if (sUserName.IsEmpty()) {
		TCHAR acUserName[100];
		DWORD nBufferSize = sizeof(acUserName);
		if (GetUserName(acUserName, &nBufferSize)) {
			sUserName = acUserName;
		}
	}


	if (sServerAddress.IsEmpty()) {
		sServerAddress = _T("localhost");
	}
}




//// LoadSetting ///////////////////////////////////////////////////////
// Loads up the value of the named registry value underneath the given
// key and returns it in pcValue.


bool
CExampleDlg::LoadSetting(HKEY key, LPCTSTR pcName, LPTSTR pcValue,
		DWORD nValueSize)
{
	return RegQueryValueEx(key, pcName, 0, 0, LPBYTE(pcValue),
			&nValueSize) == ERROR_SUCCESS;
}


//// OnBnClickedConnectButton //////////////////////////////////////////
// This is essentially the same thing as examples/simple1.cpp

void
CExampleDlg::OnBnClickedConnectButton()
{

	WCHAR awcTempBuf[100];
	const int kTempBufSize = sizeof(awcTempBuf) / sizeof(awcTempBuf[0]);

	// Pull user input into our member variables

	UpdateData(TRUE);

	// Clear out the results list, in case this isn't the first time
	// we've come in here.
	ResultsList.ResetContent();

	// Translate the Unicode text we get from the UI into the UTF-8 form

	// that MySQL wants.
	const int kInputBufSize = 100;
	char acServerAddress[kInputBufSize];
	char acUserName[kInputBufSize];
	char acPassword[kInputBufSize];
	ToUTF8(acServerAddress, kInputBufSize, sServerAddress);
	ToUTF8(acUserName, kInputBufSize, sUserName);
	ToUTF8(acPassword, kInputBufSize, sPassword);

	// Connect to the sample database.
	mysqlpp::Connection con(false);

	if (!con.connect("mysql_cpp_data", acServerAddress, acUserName,
			acPassword)) {
		AddMessage(_T("Failed to connect to server:"));
		if (ToUCS2(awcTempBuf, kTempBufSize, con.error())) {
			AddMessage(awcTempBuf);
		}
		return;
	}

	// Retrieve a subset of the sample stock table set up by resetdb
	mysqlpp::Query query = con.query();
	query << "select item from stock";
	mysqlpp::StoreQueryResult res = query.store();

	if (res) {
		// Display the result set
		for (size_t i = 0; i < res.num_rows(); ++i) {
			if (ToUCS2(awcTempBuf, kTempBufSize, res[i][0])) {
				AddMessage(awcTempBuf);
			}
		}

		// Retreive was successful, so save user inputs now
		SaveInputs();
	}
	else {













		// Retreive failed
		AddMessage(_T("Failed to get item list:"));
		if (ToUCS2(awcTempBuf, kTempBufSize, query.error())) {
			AddMessage(awcTempBuf);
		}
	}
}





//// OpenSettingsRegistryKey ///////////////////////////////////////////










HKEY
CExampleDlg::OpenSettingsRegistryKey()
{

	HKEY key1, key2;
	if ((RegOpenKey(HKEY_CURRENT_USER, _T("Software"), &key1) ==
			ERROR_SUCCESS) && (RegCreateKey(key1,
			_T("MySQL++ Examples"), &key2) == ERROR_SUCCESS)) {
		RegCloseKey(key1);
		return key2;
	}

	else {
		return 0;
	}
}






//// SaveInputs ////////////////////////////////////////////////////////
// Saves the input fields' values to the registry, except for the
// password field.

bool
CExampleDlg::SaveInputs()
{

	HKEY key = OpenSettingsRegistryKey();
	if (key) {
		SaveSetting(key, _T("user"), sUserName);
		SaveSetting(key, _T("server"), sServerAddress);
		RegCloseKey(key);
		return true;
	}

	else {
		return false;
	}
}
















//// SaveSetting ///////////////////////////////////////////////////////
// Saves the given value as a named entry under the given registry key.



bool
CExampleDlg::SaveSetting(HKEY key, LPCTSTR pcName, LPCTSTR pcValue)


{
	DWORD nBytes = DWORD(sizeof(TCHAR) * (_tcslen(pcValue) + 1));
	return RegSetValueEx(key, pcName, 0, REG_SZ, LPBYTE(pcValue),
			nBytes) == ERROR_SUCCESS;



}


//// ToUCS2 ////////////////////////////////////////////////////////////
// Convert a C string in UTF-8 format to UCS-2 format.



bool
CExampleDlg::ToUCS2(LPTSTR pcOut, int nOutLen, const char* kpcIn)
{

	if (strlen(kpcIn) > 0) {
		// Do the conversion normally
		return MultiByteToWideChar(CP_UTF8, 0, kpcIn, -1, pcOut,
				nOutLen) > 0;
	}

	else if (nOutLen > 1) {
		// Can't distinguish no bytes copied from an error, so handle
		// an empty input string as a special case.
		_tccpy(pcOut, _T(""));
		return true;
	}
	else {
		// Not enough room to do anything!
		return false;
	}
}


//// ToUTF8 ////////////////////////////////////////////////////////////
// Convert a UCS-2 multibyte string to the UTF-8 format required by
// MySQL, and thus MySQL++.

bool
CExampleDlg::ToUTF8(char* pcOut, int nOutLen, LPCWSTR kpcIn)
{







	if (_tcslen(kpcIn) > 0) {
		// Do the conversion normally
		return WideCharToMultiByte(CP_UTF8, 0, kpcIn, -1, pcOut,
				nOutLen, 0, 0) > 0;
	}
	else if (nOutLen > 0) {
		// Can't distinguish no bytes copied from an error, so handle
		// an empty input string as a special case.

		*pcOut = '\0';
		return true;







	}
	else {
		// Not enough room to do anything!
		return false;
	}

}

<
|

>
|
|
|



















|
|

|
|
<
<
<
|

<
|
<
<
|
<
<
|

<
<
<
|
<
<
|
<
<
|
<
<
<

>
|
|
<
>
|
<
>
|
|
|
<
|
|
<
>
|
|
<
>
|
<
<
>
>
|
>
|
|
|
<
>
|
|
<
>
|
<
|
>
>
|
|
|
|
|
<
<
>
>
|
|
<
<
|
|
>
>
|
|
<
|
>
|
|
|
<
<
<
<
|
|
<
<
|
<
<
<
>
|
|
|
|
>
|
|
<
|
|
|
|
>
|
<
|
|
|
|
|
|
|
<
|
>
|
<
<
<
<
<
<
<

<
<
<
<
|
|
<
<
<
<
<
<
|
<
<
<
|
>
>
>
>
>
>
>
>
>
>
>
>
>
|
|
|
|
<
<
<
|
|
>
>
>
|
>
>
>
>
>
>
>
>
>
|
|
|
<
>
|
|
|
|
|
|
<
>
|
|
<
<
|
>
>
>
>
|
|
|
|
|
|
|
<
>
|
|
|
|
|
|
<
>
|
|
<
<
>
>
>
>
>
>
>
>
>

>
>

>
>
>
|
<
>
>

<
<
>
>

<
<
<
>
>
>
|
|
|
|
<
>

>
|
<

>
|
<
<
<
<
>
|
<
<
<
|
|
<
<
<

|
|
|
<
<
<

|
<

>
>
>
>
>
>
>
|
|
|
|
|
|
|
<
>
|
|
>
>
>
>
>
>
>
|
<
<
<
|
>
|
1

2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
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

56
57


58
59
60
61
62
63
64

65
66
67

68
69

70
71
72
73
74
75
76
77


78
79
80
81


82
83
84
85
86
87

88
89
90
91
92




93
94


95



96
97
98
99
100
101
102
103

104
105
106
107
108
109

110
111
112
113
114
115
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
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
191


192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208

209
210
211


212
213
214



215
216
217
218
219
220
221

222
223
224
225

226
227
228




229
230



231
232



233
234
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
/***********************************************************************

 type_info.cpp - Implements the mysql_type_info class.

 Copyright (c) 1998 by Kevin Atkinson, (c) 1999-2001 by MySQL AB, and
 (c) 2004-2007 by Educational Technology Resources, Inc.  Others may
 also hold copyrights on code in this file.  See the CREDITS.txt file
 in the top directory of the distribution for details.

 This file is part of MySQL++.

 MySQL++ is free software; you can redistribute it and/or modify it
 under the terms of the GNU Lesser General Public License as published
 by the Free Software Foundation; either version 2.1 of the License, or
 (at your option) any later version.

 MySQL++ is distributed in the hope that it will be useful, but WITHOUT
 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
 License for more details.

 You should have received a copy of the GNU Lesser General Public
 License along with MySQL++; if not, write to the Free Software
 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
 USA
***********************************************************************/

#include "common.h"
#include "type_info.h"

#include "datetime.h"
#include "myset.h"



#include "sql_types.h"


#include <mysql.h>





#include <string>




using namespace std;





namespace mysqlpp {




// This table maps C++ type information to SQL type information.  As you
// can see, it's intimately tied in with MySQL's type constants, thus the
// name.  Unlike in earlier versions of MySQL++, this table is the only

// place with such a dependency.  Everything else abstracts MySQL's
// type system away by bouncing things through this table.

//
// The second half of the table parallels the first, to handle null-able
// versions of the types in the first half.  This is required because
// SQL's 'null' concept does not map neatly into the C++ type system, so

// null-able versions of these types have to have a different C++ type,
// implemented using the Null template.  See null.h for further details.

//
// Types with tf_default set are added to a lookup map in the
// mysql_type_info_lookup class in order to provide reverse lookup

// of C++ types to SQL types.  If you take the subset of all items
// marked as default, the typeid() of each item must be unique.


const mysql_type_info::sql_type_info mysql_type_info::types[] = {
	sql_type_info("DECIMAL NOT NULL", typeid(sql_decimal),
#if MYSQL_VERSION_ID >= 50001
			MYSQL_TYPE_NEWDECIMAL
#else
			MYSQL_TYPE_DECIMAL
#endif

			),
	sql_type_info("TINYINT NOT NULL", typeid(sql_tinyint),
			MYSQL_TYPE_TINY, mysql_ti_sql_type_info::tf_default),

	sql_type_info("TINYINT UNSIGNED NOT NULL", typeid(sql_tinyint_unsigned),
			MYSQL_TYPE_TINY, mysql_ti_sql_type_info::tf_default |

			mysql_ti_sql_type_info::tf_unsigned),
	sql_type_info("SMALLINT NOT NULL", typeid(sql_smallint),
			MYSQL_TYPE_SHORT, mysql_ti_sql_type_info::tf_default),
	sql_type_info("SMALLINT UNSIGNED NOT NULL", typeid(sql_smallint_unsigned),
			MYSQL_TYPE_SHORT, mysql_ti_sql_type_info::tf_default |
			mysql_ti_sql_type_info::tf_unsigned),
	sql_type_info("INT NOT NULL", typeid(sql_int),
			MYSQL_TYPE_LONG, mysql_ti_sql_type_info::tf_default),


	sql_type_info("INT UNSIGNED NOT NULL", typeid(sql_int_unsigned),
			MYSQL_TYPE_LONG, mysql_ti_sql_type_info::tf_default |
			mysql_ti_sql_type_info::tf_unsigned),
	sql_type_info("FLOAT NOT NULL", typeid(sql_float),


			MYSQL_TYPE_FLOAT, mysql_ti_sql_type_info::tf_default),
	sql_type_info("DOUBLE NOT NULL", typeid(sql_double),
			MYSQL_TYPE_DOUBLE, mysql_ti_sql_type_info::tf_default),
	sql_type_info("NULL NOT NULL", typeid(void),
			MYSQL_TYPE_NULL, mysql_ti_sql_type_info::tf_default),
	sql_type_info("TIMESTAMP NOT NULL", typeid(sql_timestamp),

			MYSQL_TYPE_TIMESTAMP),
	sql_type_info("BIGINT NOT NULL", typeid(sql_bigint),
			MYSQL_TYPE_LONGLONG, mysql_ti_sql_type_info::tf_default),
	sql_type_info("BIGINT UNSIGNED NOT NULL", typeid(sql_bigint_unsigned),
			MYSQL_TYPE_LONGLONG, mysql_ti_sql_type_info::tf_default |




			mysql_ti_sql_type_info::tf_unsigned),
	sql_type_info("MEDIUMINT NOT NULL", typeid(sql_mediumint),


			MYSQL_TYPE_INT24, mysql_ti_sql_type_info::tf_unsigned),



	sql_type_info("MEDIUMINT UNSIGNED NOT NULL", typeid(sql_mediumint_unsigned),
			MYSQL_TYPE_INT24, mysql_ti_sql_type_info::tf_unsigned),
	sql_type_info("DATE NOT NULL", typeid(sql_date),
			MYSQL_TYPE_DATE, mysql_ti_sql_type_info::tf_default),
	sql_type_info("TIME NOT NULL", typeid(sql_time),
			MYSQL_TYPE_TIME, mysql_ti_sql_type_info::tf_default),
	sql_type_info("DATETIME NOT NULL", typeid(sql_datetime),
			MYSQL_TYPE_DATETIME, mysql_ti_sql_type_info::tf_default),

	sql_type_info("ENUM NOT NULL", typeid(sql_enum),
			MYSQL_TYPE_ENUM, mysql_ti_sql_type_info::tf_default),
	sql_type_info("SET NOT NULL", typeid(sql_set),
			MYSQL_TYPE_SET, mysql_ti_sql_type_info::tf_default),
	sql_type_info("TINYBLOB NOT NULL", typeid(sql_tinyblob),
			MYSQL_TYPE_TINY_BLOB),

	sql_type_info("MEDIUMBLOB NOT NULL", typeid(sql_mediumblob),
			MYSQL_TYPE_MEDIUM_BLOB),
	sql_type_info("LONGBLOB NOT NULL", typeid(sql_longblob),
			MYSQL_TYPE_LONG_BLOB),
	sql_type_info("BLOB NOT NULL", typeid(sql_blob),
			MYSQL_TYPE_BLOB, mysql_ti_sql_type_info::tf_default),
	sql_type_info("VARCHAR NOT NULL", typeid(sql_varchar),

			MYSQL_TYPE_VAR_STRING, mysql_ti_sql_type_info::tf_default),
	sql_type_info("CHAR NOT NULL", typeid(sql_char),
			MYSQL_TYPE_STRING),












	sql_type_info("DECIMAL NULL", typeid(Null<sql_decimal>),
#if MYSQL_VERSION_ID >= 50001






			MYSQL_TYPE_NEWDECIMAL



#else
			MYSQL_TYPE_DECIMAL
#endif
			, mysql_ti_sql_type_info::tf_null),
	sql_type_info("TINYINT NULL", typeid(Null<sql_tinyint>),
			MYSQL_TYPE_TINY, mysql_ti_sql_type_info::tf_default |
			mysql_ti_sql_type_info::tf_null),
	sql_type_info("TINYINT UNSIGNED NULL", typeid(Null<sql_tinyint_unsigned>),
			MYSQL_TYPE_TINY, mysql_ti_sql_type_info::tf_default |
			mysql_ti_sql_type_info::tf_null |
			mysql_ti_sql_type_info::tf_unsigned),
	sql_type_info("SMALLINT NULL", typeid(Null<sql_smallint>),
			MYSQL_TYPE_SHORT, mysql_ti_sql_type_info::tf_default |
			mysql_ti_sql_type_info::tf_null),
	sql_type_info("SMALLINT UNSIGNED NULL", typeid(Null<sql_smallint_unsigned>),
			MYSQL_TYPE_SHORT, mysql_ti_sql_type_info::tf_default |
			mysql_ti_sql_type_info::tf_null |
			mysql_ti_sql_type_info::tf_unsigned),



	sql_type_info("INT NULL", typeid(Null<sql_int>),
			MYSQL_TYPE_LONG, mysql_ti_sql_type_info::tf_default |
			mysql_ti_sql_type_info::tf_null),
	sql_type_info("INT UNSIGNED NULL", typeid(Null<sql_int_unsigned>),
			MYSQL_TYPE_LONG, mysql_ti_sql_type_info::tf_default |
			mysql_ti_sql_type_info::tf_null |
			mysql_ti_sql_type_info::tf_unsigned),
	sql_type_info("FLOAT NULL", typeid(Null<sql_float>),
			MYSQL_TYPE_FLOAT, mysql_ti_sql_type_info::tf_default |
			mysql_ti_sql_type_info::tf_null),
	sql_type_info("DOUBLE NULL", typeid(Null<sql_double>),
			MYSQL_TYPE_DOUBLE, mysql_ti_sql_type_info::tf_default |
			mysql_ti_sql_type_info::tf_null),
	sql_type_info("NULL NULL", typeid(Null<void>),
			MYSQL_TYPE_NULL, mysql_ti_sql_type_info::tf_null),
	sql_type_info("TIMESTAMP NULL", typeid(Null<sql_timestamp>),
			MYSQL_TYPE_TIMESTAMP),
	sql_type_info("BIGINT NULL", typeid(Null<sql_bigint>),

			MYSQL_TYPE_LONGLONG, mysql_ti_sql_type_info::tf_default |
			mysql_ti_sql_type_info::tf_null),
	sql_type_info("BIGINT UNSIGNED NULL", typeid(Null<sql_bigint_unsigned>),
			MYSQL_TYPE_LONGLONG, mysql_ti_sql_type_info::tf_default |
			mysql_ti_sql_type_info::tf_null |
			mysql_ti_sql_type_info::tf_unsigned),
	sql_type_info("MEDIUMINT NULL", typeid(Null<sql_mediumint>),

			MYSQL_TYPE_INT24, mysql_ti_sql_type_info::tf_null),
	sql_type_info("MEDIUMINT UNSIGNED NULL", typeid(Null<sql_mediumint_unsigned>), 
			MYSQL_TYPE_INT24, mysql_ti_sql_type_info::tf_null |


			mysql_ti_sql_type_info::tf_unsigned),
	sql_type_info("DATE NULL", typeid(Null<sql_date>),
			MYSQL_TYPE_DATE, mysql_ti_sql_type_info::tf_default |
			mysql_ti_sql_type_info::tf_null),
	sql_type_info("TIME NULL", typeid(Null<sql_time>),
			MYSQL_TYPE_TIME, mysql_ti_sql_type_info::tf_default |
			mysql_ti_sql_type_info::tf_null),
	sql_type_info("DATETIME NULL", typeid(Null<sql_datetime>),
			MYSQL_TYPE_DATETIME, mysql_ti_sql_type_info::tf_default |
			mysql_ti_sql_type_info::tf_null),
	sql_type_info("ENUM NULL", typeid(Null<sql_enum>),
			MYSQL_TYPE_ENUM, mysql_ti_sql_type_info::tf_default |

			mysql_ti_sql_type_info::tf_null),
	sql_type_info("SET NULL", typeid(Null<sql_set>),
			MYSQL_TYPE_SET, mysql_ti_sql_type_info::tf_default |
			mysql_ti_sql_type_info::tf_null),
	sql_type_info("TINYBLOB NULL", typeid(Null<sql_tinyblob>),
			MYSQL_TYPE_TINY_BLOB, mysql_ti_sql_type_info::tf_null),
	sql_type_info("MEDIUMBLOB NULL", typeid(Null<sql_mediumblob>),

			MYSQL_TYPE_MEDIUM_BLOB, mysql_ti_sql_type_info::tf_null),
	sql_type_info("LONGBLOB NULL", typeid(Null<sql_longblob>),
			MYSQL_TYPE_LONG_BLOB, mysql_ti_sql_type_info::tf_null),


	sql_type_info("BLOB NULL", typeid(Null<sql_blob>),
			MYSQL_TYPE_BLOB, mysql_ti_sql_type_info::tf_default |
			mysql_ti_sql_type_info::tf_null),
	sql_type_info("VARCHAR NULL", typeid(Null<sql_varchar>),
			MYSQL_TYPE_VAR_STRING, mysql_ti_sql_type_info::tf_default |
			mysql_ti_sql_type_info::tf_null),
	sql_type_info("CHAR NULL", typeid(Null<sql_char>),
			MYSQL_TYPE_STRING, mysql_ti_sql_type_info::tf_null)
};

const int mysql_type_info::num_types =
		sizeof(mysql_type_info::types) / sizeof(mysql_type_info::types[0]);

const mysql_type_info::sql_type_info_lookup
		mysql_type_info::lookups(mysql_type_info::types,
		mysql_type_info::num_types);


#if !defined(DOXYGEN_IGNORE)
// Doxygen will not generate documentation for this section.



mysql_ti_sql_type_info_lookup::mysql_ti_sql_type_info_lookup(
		const sql_type_info types[], const int size)
{



	for (int i = 0; i < size; ++i) {
		if (types[i].is_default()) {
			map_[types[i].c_type_] = i;
		}
	}
}


#endif // !defined(DOXYGEN_IGNORE)

unsigned char mysql_type_info::type(enum_field_types t,
		bool _unsigned, bool _null)

{
	for (unsigned char i = 0; i < num_types; ++i) {
		if ((types[i].base_type_ == t) &&




				(!_unsigned || types[i].is_unsigned()) &&
				(!_null || types[i].is_null())) {



			return i;
		}



	}

	return type(MYSQL_TYPE_STRING, false, _null);	// punt!
}




bool mysql_type_info::quote_q() const

{
	const type_info& ti = base_type().c_type();
	return ti == typeid(string) ||
			ti == typeid(sql_date) ||
			ti == typeid(sql_time) ||
			ti == typeid(sql_datetime) ||
			ti == typeid(sql_blob) ||
			ti == typeid(sql_tinyblob) ||
			ti == typeid(sql_mediumblob) ||
			ti == typeid(sql_longblob) ||
			ti == typeid(sql_char) ||
			ti == typeid(sql_set);
}

bool mysql_type_info::escape_q() const

{
	const type_info& ti = c_type();
	return ti == typeid(string) ||
			ti == typeid(sql_enum) ||
			ti == typeid(sql_blob) ||
			ti == typeid(sql_tinyblob) ||
			ti == typeid(sql_mediumblob) ||
			ti == typeid(sql_longblob) ||
			ti == typeid(sql_char) ||
			ti == typeid(sql_varchar);
}




} // end namespace mysqlpp

Changes to examples/vstudio/mfc/mfc_dlg.h.







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


26
27


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







56









57










































































































































58











/***********************************************************************
 mfc_dlg.h - Declares the dialog class for the MySQL++ MFC example.

 Copyright (c) 2007 by Educational Technology Resources, Inc.  Others 
 may also hold copyrights on code in this file.  See the CREDITS.txt
 file in the top directory of the distribution for details.

 This file is part of MySQL++.

 MySQL++ is free software; you can redistribute it and/or modify it
 under the terms of the GNU Lesser General Public License as published
 by the Free Software Foundation; either version 2.1 of the License, or
 (at your option) any later version.

 MySQL++ is distributed in the hope that it will be useful, but WITHOUT
 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
 License for more details.

 You should have received a copy of the GNU Lesser General Public
 License along with MySQL++; if not, write to the Free Software
 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
 USA
***********************************************************************/



#pragma once
#include "afxwin.h"


#include "resource.h"


class CExampleDlg : public CDialog

{


public:
	//// Public interface





	CExampleDlg(CWnd* pParent = 0);



	//// Public data
	CString sServerAddress;

	CString sUserName;


	CString sPassword;



	CListBox ResultsList;


protected:





	//// Internal support functions





	void AddMessage(LPCTSTR pcMessage);



	void DoDataExchange(CDataExchange* pDX);








































































	void LoadDefaults();










	bool LoadSetting(HKEY key, LPCTSTR pcName, LPTSTR pcValue,



			DWORD nValueSize);
	HKEY OpenSettingsRegistryKey();


	bool SaveInputs();









	bool SaveSetting(HKEY key, LPCTSTR pcName, LPCTSTR pcValue);






	bool ToUCS2(LPTSTR pcOut, int nOutLen, const char* kpcIn);





	bool ToUTF8(char* pcOut, int nOutLen, LPCWSTR kpcIn);





























































	//// Message map







	afx_msg void OnBnClickedConnectButton();









	DECLARE_MESSAGE_MAP()










































































































































};





>
>
>
>
>
>

<
|
|
|
|



















>
>
|
|
>
>
|

>
|
>
|
>
>

|
>
>
>
>
>
|
>
>
|
|
|
>
|
>
>
|
>
>
>
|
>


>
>
>
>
>
|
>
>
>
>
>
|
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
|
>
>
>
|
|
>
>
|
>
>
>
>
>
>
>
>
>
|
>
>
>
>
>
>
|
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

>
>
>
>
|
>
>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

>
>
>
>
>
1
2
3
4
5
6
7

8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
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
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
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
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
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
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
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
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
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
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
/// \file exceptions.h
/// \brief Declares the MySQL++-specific exception classes.
///
/// When exceptions are enabled for a given mysqlpp::OptionalExceptions
/// derivative, any of these exceptions can be thrown on error.

/***********************************************************************

 Copyright (c) 1998 by Kevin Atkinson, (c) 1999-2001 by MySQL AB, and
 (c) 2004-2007 by Educational Technology Resources, Inc.  Others may
 also hold copyrights on code in this file.  See the CREDITS file in
 the top directory of the distribution for details.

 This file is part of MySQL++.

 MySQL++ is free software; you can redistribute it and/or modify it
 under the terms of the GNU Lesser General Public License as published
 by the Free Software Foundation; either version 2.1 of the License, or
 (at your option) any later version.

 MySQL++ is distributed in the hope that it will be useful, but WITHOUT
 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
 License for more details.

 You should have received a copy of the GNU Lesser General Public
 License along with MySQL++; if not, write to the Free Software
 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
 USA
***********************************************************************/

#if !defined(MYSQLPP_EXCEPTIONS_H)
#define MYSQLPP_EXCEPTIONS_H

#include "options.h"

#include <exception>
#include <string>

namespace mysqlpp {

/// \brief Base class for all MySQL++ custom exceptions

class MYSQLPP_EXPORT Exception : public std::exception
{
public:
	/// \brief Create exception object as copy of another
	Exception(const Exception& e) throw() :
	std::exception(e),
	what_(e.what_)
	{
	}

	/// \brief Assign another exception object's contents to this one
	Exception& operator=(const Exception& rhs) throw()
	{
		what_ = rhs.what_;
		return *this;
	}

	/// \brief Destroy exception object
	~Exception() throw() { }

	/// \brief Returns explanation of why exception was thrown
	virtual const char* what() const throw()
	{
		return what_.c_str();
	}

protected:
	/// \brief Create exception object
	Exception(const char* w = "") throw() :
	what_(w)
	{
	}

	/// \brief Create exception object
	Exception(const std::string& w) throw() :
	what_(w)
	{
	}

	/// \brief explanation of why exception was thrown
	std::string what_;
};


/// \brief Exception thrown when a bad type conversion is attempted.

class MYSQLPP_EXPORT BadConversion : public Exception
{
public:
	const char* type_name;	///< name of type we tried to convert to
	std::string data;		///< string form of data we tried to convert
	size_t retrieved;		///< documentation needed!
	size_t actual_size;		///< documentation needed!

	/// \brief Create exception object, building error string
	/// dynamically
	///
	/// \param tn type name we tried to convert to
	/// \param d string form of data we tried to convert
	/// \param r ??
	/// \param a ??
	BadConversion(const char* tn, const char* d,
			size_t r, size_t a) :
	Exception("Bad type conversion: \""),
	type_name(tn),
	data(d),
	retrieved(r),
	actual_size(a)
	{
		what_ += d ? d : "<NULL>";
		what_ += "\" incompatible with \"";
		what_ += tn;
		what_ += "\" type";
	}

	/// \brief Create exception object, given completed error string
	///
	/// \param w the "what" error string
	/// \param tn type name we tried to convert to
	/// \param d string form of data we tried to convert
	/// \param r ??
	/// \param a ??
	BadConversion(const std::string& w, const char* tn,
				  const char* d, size_t r, size_t a) :
	Exception(w),
	type_name(tn),
	data(d),
	retrieved(r),
	actual_size(a)
	{
	}

	/// \brief Create exception object, with error string only
	///
	/// \param w the "what" error string
	///
	/// All other data members are initialize to default values
	explicit BadConversion(const char* w = "") :
	Exception(w),
	type_name("unknown"),
	data(""),
	retrieved(0),
	actual_size(0)
	{
	}

	/// \brief Destroy exception
	~BadConversion() throw() { }
};


/// \brief Exception thrown when a requested named field doesn't exist.
///
/// Thrown by Row::lookup_by_name() when you pass a field name that
/// isn't in the result set.

class MYSQLPP_EXPORT BadFieldName : public Exception
{
public:
	/// \brief Create exception object
	///
	/// \param bad_field name of field the database server didn't like
	explicit BadFieldName(const char* bad_field) :
	Exception(std::string("Unknown field name: ") + bad_field)
	{
	}

	/// \brief Destroy exception
	~BadFieldName() throw() { }
};


/// \brief Exception thrown when you pass an unrecognized option to
/// Connection::set_option().

class MYSQLPP_EXPORT BadOption : public Exception
{
public:
	/// \brief Create exception object, taking C string
	explicit BadOption(const char* w, const std::type_info& ti) :
	Exception(w),
	ti_(ti)
	{
	}

	/// \brief Create exception object, taking C++ string
	explicit BadOption(const std::string& w, const std::type_info& ti) :
	Exception(w),
	ti_(ti)
	{
	}

	/// \brief Return type information about the option that failed
	///
	/// Because each option has its own C++ type, this lets you
	/// distinguish among BadOption exceptions programmatically.
	const std::type_info& what_option() const { return ti_; }

private:
	const std::type_info& ti_;
};


/// \brief Exception thrown when not enough query parameters are
/// provided.
///
/// This is used in handling template queries.

class MYSQLPP_EXPORT BadParamCount : public Exception
{
public:
	/// \brief Create exception object
	explicit BadParamCount(const char* w = "") :
	Exception(w)
	{
	}

	/// \brief Destroy exception
	~BadParamCount() throw() { }
};

/// \brief Exception thrown when something goes wrong in processing a
/// "use" query.

class MYSQLPP_EXPORT UseQueryError : public Exception
{
public:
	/// \brief Create exception object
	explicit UseQueryError(const char* w = "") :
	Exception(w)
	{
	}
};


/// \brief Exception thrown when the database server encounters a problem
/// while processing your query.
///
/// Unlike most other MySQL++ exceptions, which carry just an error
/// message, this type carries an error number to preserve
/// Connection::errnum()'s return value at the point the exception is 
/// thrown.  We do this because when using the Transaction class, the
/// rollback process that occurs during stack unwinding issues a query
/// to the database server, overwriting the error value.  This rollback
/// should always succeed, so this effect can fool code that relies on
/// Connection::errnum() into believing that there was no error.
///
/// Beware that in older versions of MySQL++, this was effectively the
/// generic exception type.  (This is most especially true in v1.7.x,
/// but it continued to a lesser extent through the v2.x series.)  When
/// converting old code to new versions of MySQL++, it's therefore
/// possible to get seemingly "new" exceptions thrown, which could crash
/// your program if you don't also catch a more generic type like
/// mysqlpp::Exception or std::exception.

class MYSQLPP_EXPORT BadQuery : public Exception
{
public:
	/// \brief Create exception object
	///
	/// \param w explanation for why the exception was thrown
	/// \param e the error number from the underlying database API
	explicit BadQuery(const char* w = "", int e = 0) :
	Exception(w), 
	errnum_(e)
	{
	}

	/// \brief Create exception object
	///
	/// \param w explanation for why the exception was thrown
	/// \param e the error number from the underlying database API
	explicit BadQuery(const std::string& w, int e = 0) :
	Exception(w), 
	errnum_(e)
	{
	}

	/// \brief Return the error number corresponding to the error
	/// message returned by what()
	///
	/// This may return the same value as Connection::errnum(), but not
	/// always.  See the overview documentation for this class for the
	/// reason for the difference.
	int errnum() const { return errnum_; }
	
private:	
	int	errnum_;	///< error number associated with execption
};


/// \brief Exception thrown when there is a problem related to the
/// database server connection.
///
/// This is thrown not just on making the connection, but also on
/// shutdown and when calling certain of Connection's methods that
/// require a connection when there isn't one.

class MYSQLPP_EXPORT ConnectionFailed : public Exception
{
public:
	/// \brief Create exception object
	///
	/// \param w explanation for why the exception was thrown
	/// \param e the error number from the underlying database API
	explicit ConnectionFailed(const char* w = "", int e = 0) :
	Exception(w),
	errnum_(e)
	{
	}

	/// \brief Return the error number corresponding to the error
	/// message returned by what(), if any.
	///
	/// If the error number is 0, it means that the error message
	/// doesn't come from the underlying database API, but rather from
	/// MySQL++ itself.  This happens when an error condition is
	/// detected up at this higher level instead of letting the
	/// underlying database API do it.
	int errnum() const { return errnum_; }
	
private:	
	int	errnum_;	///< error number associated with execption
};


/// \brief Exception thrown when the program tries to select a new
/// database and the database server refuses for some reason.

class MYSQLPP_EXPORT DBSelectionFailed : public Exception
{
public:
	/// \brief Create exception object
	///
	/// \param w explanation for why the exception was thrown
	/// \param e the error number from the underlying database API
	explicit DBSelectionFailed(const char* w = "", int e = 0) :
	Exception(w),
	errnum_(e)
	{
	}

	/// \brief Return the error number corresponding to the error
	/// message returned by what(), if any.
	///
	/// If the error number is 0, it means that the error message
	/// doesn't come from the underlying database API, but rather from
	/// MySQL++ itself.  This happens when an error condition is
	/// detected up at this higher level instead of letting the
	/// underlying database API do it.
	int errnum() const { return errnum_; }
	
private:	
	int	errnum_;	///< error number associated with execption
};


/// \brief Exception thrown when a BeecryptMutex object fails.

class MYSQLPP_EXPORT MutexFailed : public Exception
{
public:
	/// \brief Create exception object
	explicit MutexFailed(const char* w = "lock failed") :
	Exception(w)
	{
	}
};


/// \brief Exception thrown when you try to use an object that isn't
/// completely initialized.

class MYSQLPP_EXPORT ObjectNotInitialized : public Exception
{
public:
	/// \brief Create exception object
	explicit ObjectNotInitialized(const char* w = "") :
	Exception(w)
	{
	}
};


/// \brief Used within MySQL++'s test harness only.

class MYSQLPP_EXPORT SelfTestFailed : public Exception
{
public:
	/// \brief Create exception object
	explicit SelfTestFailed(const std::string& w) :
	Exception(w)
	{
	}
};


/// \brief Thrown from the C++ to SQL data type conversion routine when
/// it can't figure out how to map the type.
///
/// This exception is not optional.  The only alternatives when this
/// happens are equally drastic: basically, either iterate past the
/// end of an array (crashing the program) or call assert() to crash
/// the program nicely.  At least this way you have some control over
/// how your program ends.  You can even ignore the error and keep on
/// going: this typically happens when building a SQL query, so you can
/// handle it just the same as if the subsequent query execution failed.

class MYSQLPP_EXPORT TypeLookupFailed : public Exception
{
public:
	/// \brief Create exception object
	explicit TypeLookupFailed(const std::string& w) :
	Exception(w)
	{
	}
};


} // end namespace mysqlpp

#endif // !defined(MYSQLPP_EXCEPTIONS_H)

Changes to examples/vstudio/mfc/resource.h.

1
2
3
4
5
6
7
8
9
10
11




12



13
14





15
16

17

18

19

20



21











































22
//{{NO_DEPENDENCIES}}
// Microsoft Visual C++ generated include file.
// Used by mfc.rc
//
#define IDD_MFC_DIALOG                  102
#define IDP_SOCKETS_INIT_FAILED         103
#define IDC_SERVER_EDIT                 1000
#define IDC_PASSWORD_EDIT               1001
#define IDC_USER_EDIT                   1002
#define IDC_RESULTS_LIST                1003
#define IDC_CONNECT_BUTTON              1004








// Next default values for new objects
// 





#ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS

#define _APS_NEXT_RESOURCE_VALUE        129

#define _APS_NEXT_COMMAND_VALUE         32771

#define _APS_NEXT_CONTROL_VALUE         1005

#define _APS_NEXT_SYMED_VALUE           101



#endif











































#endif
|
|
|
|
|
|
|
|
|
|
|
>
>
>
>

>
>
>
|
|
>
>
>
>
>
|
|
>
|
>
|
>
|
>
|
>
>
>

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
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
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
/// \file field_types.h
/// \brief Declares a class to hold a list of SQL field type info.

/***********************************************************************
 Copyright (c) 1998 by Kevin Atkinson, (c) 1999, 2000 and 2001 by
 MySQL AB, and (c) 2004-2007 by Educational Technology Resources, Inc.
 Others may also hold copyrights on code in this file.  See the CREDITS
 file in the top directory of the distribution for details.

 This file is part of MySQL++.

 MySQL++ is free software; you can redistribute it and/or modify it
 under the terms of the GNU Lesser General Public License as published
 by the Free Software Foundation; either version 2.1 of the License, or
 (at your option) any later version.

 MySQL++ is distributed in the hope that it will be useful, but WITHOUT
 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
 License for more details.

 You should have received a copy of the GNU Lesser General Public
 License along with MySQL++; if not, write to the Free Software
 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
 USA
***********************************************************************/

#ifndef MYSQLPP_FIELD_TYPES_H
#define MYSQLPP_FIELD_TYPES_H

#include "type_info.h"

#include <vector>

namespace mysqlpp {

#if !defined(DOXYGEN_IGNORE)
// Make Doxygen ignore this
class MYSQLPP_EXPORT ResultBase;
#endif

/// \brief A vector of SQL field types.
class FieldTypes : public std::vector<mysql_type_info>
{
public:
	/// \brief Default constructor
	FieldTypes() { }
	
	/// \brief Create list of field types from a result set
	FieldTypes(const ResultBase* res)
	{
		init(res);
	}

	/// \brief Create fixed-size list of uninitialized field types
	FieldTypes(int i) :
	std::vector<mysql_type_info>(i)
	{
	}

	/// \brief Initialize field list based on a result set
	FieldTypes& operator =(const ResultBase* res)
	{
		init(res);
		return *this;
	}

	/// \brief Insert a given number of uninitialized field type
	/// objects at the beginning of the list
	///
	/// \param i number of field type objects to insert
	FieldTypes& operator =(int i)
	{
		insert(begin(), i, mysql_type_info());
		return *this;
	}

private:
	void init(const ResultBase* res);
};

} // end namespace mysqlpp

#endif

Changes to examples/vstudio/mfc/stdafx.h.

















1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26


27

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




































































































/***********************************************************************
 stdafx.h - Common include file to bring in MFC support and other
	basics.

 Copyright (c) 2007 by Educational Technology Resources, Inc.  Others 
 may also hold copyrights on code in this file.  See the CREDITS.txt
 file in the top directory of the distribution for details.

 This file is part of MySQL++.

 MySQL++ is free software; you can redistribute it and/or modify it
 under the terms of the GNU Lesser General Public License as published
 by the Free Software Foundation; either version 2.1 of the License, or
 (at your option) any later version.

 MySQL++ is distributed in the hope that it will be useful, but WITHOUT
 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
 License for more details.

 You should have received a copy of the GNU Lesser General Public
 License along with MySQL++; if not, write to the Free Software
 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
 USA
***********************************************************************/



#pragma once




#ifndef VC_EXTRALEAN

#define VC_EXTRALEAN		// Exclude rarely-used stuff from Windows headers






























































































#endif














// Modify the following defines if you have to target a platform prior to the ones specified below.
// Refer to MSDN for the latest info on corresponding values for different platforms.


#ifndef WINVER				// Allow use of features specific to Windows XP or later.








#define WINVER 0x0501		// Change this to the appropriate value to target other versions of Windows.
#endif





#ifndef _WIN32_WINNT		// Allow use of features specific to Windows XP or later.                   
#define _WIN32_WINNT 0x0501	// Change this to the appropriate value to target other versions of Windows.






































#endif						

















































#ifndef _WIN32_WINDOWS		// Allow use of features specific to Windows 98 or later.
#define _WIN32_WINDOWS 0x0410 // Change this to the appropriate value to target Windows Me or later.





























#endif

// turns off MFC's hiding of some common and often safely ignored warning messages










#define _AFX_ALL_WARNINGS











































































#include <afxwin.h>         // MFC core and standard components
#include <afxext.h>         // MFC extensions


#include <afxcmn.h>			// MFC support for Windows Common Controls








#include <afxsock.h>		// MFC socket extensions





















































































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

<
<
|
|
|
|



















>
>
|
>

>
>
|
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>

>
>
>
>
|
|
>
>
|
>
>
>
>
>
>
>
>
|
|
>
>
|
>
>
|
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
>
|
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|

|
>
>
>
>
>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

>
>
>
>
|
|
>
>
|
>
>
>
>
>
>
>
>
|

>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17


18
19
20
21
22
23
24
25
26
27
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
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
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
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
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
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
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
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
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
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
/// \file manip.h
/// \brief Declares the Query stream manipulators and operators.
///
/// These manipulators let you automatically quote elements or escape
/// characters that are special in SQL when inserting them into a
/// Query stream.  They make it easier to build syntactically-correct
/// SQL queries.
///
/// This file also includes special \c operator<< definitions for a few
/// key MySQL++ data types, since we know when to do automatic quoting
/// and escaping for these types.  This only works with Query streams,
/// not regular std::ostreams, since we're only concerned with making
/// correct SQL, not with presentation matters.
///
/// test/test_manip.cpp exercises the mechanisms defined here.

/***********************************************************************


 Copyright (c) 1998 by Kevin Atkinson, (c) 1999-2001 by MySQL AB, and
 (c) 2004-2007 by Educational Technology Resources, Inc.  Others may
 also hold copyrights on code in this file.  See the CREDITS file in
 the top directory of the distribution for details.

 This file is part of MySQL++.

 MySQL++ is free software; you can redistribute it and/or modify it
 under the terms of the GNU Lesser General Public License as published
 by the Free Software Foundation; either version 2.1 of the License, or
 (at your option) any later version.

 MySQL++ is distributed in the hope that it will be useful, but WITHOUT
 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
 License for more details.

 You should have received a copy of the GNU Lesser General Public
 License along with MySQL++; if not, write to the Free Software
 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
 USA
***********************************************************************/

#ifndef MYSQLPP_MANIP_H
#define MYSQLPP_MANIP_H

#include "common.h"

#include "myset.h"
#include "stadapter.h"

#include <iostream>

namespace mysqlpp {

class SQLQueryParms;


/// \enum quote_type0
/// \anchor quote_manip
///
/// The standard 'quote' manipulator.  It is the most widely useful
/// manipulator in MySQL++.
///
/// Insert this manipulator into a Query or SQLQueryParms stream to put
/// single quotes around the next item in the stream, and escape any
/// characters within it that are special in SQL, if the data type of
/// the next item in the stream may require it.  By contrast, Date
/// objects only require escaping, not quoting, and integers never
/// require either.  The manipulators won't do work they know is not
/// necessary to ensure syntactially-correct SQL.

enum quote_type0
{
	quote ///< insert into a Query stream to single-quote and escape next item
};


#if !defined(DOXYGEN_IGNORE)
// Doxygen will not generate documentation for this section.

struct quote_type1
{
	std::ostream * ostr;
	quote_type1(std::ostream * o) :
	ostr(o)
	{
	}
};


inline quote_type1
operator <<(std::ostream& o, quote_type0 /* esc */)
{
	return quote_type1(&o);
}


struct quote_type2
{
	SQLQueryParms *qparms;
	quote_type2(SQLQueryParms* p) :
	qparms(p)
	{
	}
};


inline quote_type2
operator <<(SQLQueryParms& p, quote_type0 /* esc */)
{
	return quote_type2(&p);
}


/// \brief Inserts a SQLTypeAdapter into a stream, quoted and escaped
/// as appropriate to the data type the object was initialized from.

MYSQLPP_EXPORT SQLQueryParms& operator <<(quote_type2 p,
		SQLTypeAdapter& in);


/// \brief Inserts a anything that can be converted to SQLTypeAdapter
/// into a stream, quoted and escaped as needed if it's a Query stream

MYSQLPP_EXPORT std::ostream& operator <<(quote_type1 o,
		const SQLTypeAdapter& in);


/// \brief Inserts a SQLTypeAdapter into a non-Query stream.
///
/// Although we know how to quote and escape SQLTypeAdapter objects, we
/// only do that when inserting them into Query streams or when given an
/// explicit manipulator because this feature is only intended to make
/// it easier to build syntactically-correct SQL queries.

MYSQLPP_EXPORT std::ostream& operator <<(std::ostream& o,
		const SQLTypeAdapter& in);


template <class ST>
inline std::ostream& 
operator <<(quote_type1 o, const Set<ST>& in)
{
	return *o.ostr << '\'' << in << '\'';
}

#endif // !defined(DOXYGEN_IGNORE)


/// \enum quote_only_type0
/// \anchor quote_only_manip
///
/// The 'quote_only' manipulator.
///
/// Similar to <a href="#quote_manip">quote manipulator</a>, except that
/// it doesn't escape special SQL characters.

enum quote_only_type0
{
	quote_only				///< insert into a std::ostream to single-quote next item
};


#if !defined(DOXYGEN_IGNORE)
// Doxygen will not generate documentation for this section.

struct quote_only_type1
{
	std::ostream* ostr;
	quote_only_type1(std::ostream* o) :
	ostr(o)
	{
	}
};


inline quote_only_type1
operator <<(std::ostream& o, quote_only_type0 /* esc */)
{
	return quote_only_type1(&o);
}


struct quote_only_type2
{
	SQLQueryParms* qparms;
	quote_only_type2(SQLQueryParms* p) :
	qparms(p)
	{
	}
};


inline quote_only_type2 
operator <<(SQLQueryParms& p, quote_only_type0 /* esc */)
{
	return quote_only_type2(&p);
}


/// \brief Inserts a SQLTypeAdapter into a stream, quoting it unless it's
/// data that needs no quoting.
///
/// We make the decision to quote the data based on the in.quote_q()
/// flag.  You can set it yourself, but SQLTypeAdapter's ctors should set
/// it correctly for you.

MYSQLPP_EXPORT SQLQueryParms& operator <<(quote_only_type2 p,
		SQLTypeAdapter& in);


std::ostream& operator <<(quote_only_type1 o, const SQLTypeAdapter& in);


template <class ST>
inline std::ostream& 
operator <<(quote_only_type1 o, const Set<ST>& in)
{
	return *o.ostr << '\'' << in << '\'';
}

#endif // !defined(DOXYGEN_IGNORE)


/// \enum quote_double_only_type0
/// \anchor quote_double_manip
///
/// The 'double_quote_only' manipulator.
///
/// Similar to <a href="#quote_only_manip">quote_only manipulator</a>,
/// except that it uses double quotes instead of single quotes.
///
/// You might care to use it when you have MySQL's \c ANSI_QUOTES mode
/// enabled.  In that mode, single quotes are used only for string
/// literals, and double quotes for identifiers.  Otherwise,
/// \c quote_only and \c quote are quite sufficient.

enum quote_double_only_type0
{
	quote_double_only ///< insert into a std::ostream to double-quote next item
};


#if !defined(DOXYGEN_IGNORE)
// Doxygen will not generate documentation for this section.

struct quote_double_only_type1
{
	std::ostream* ostr;
	quote_double_only_type1(std::ostream* o) :
	ostr(o)
	{
	}
};


inline quote_double_only_type1
operator <<(std::ostream& o, quote_double_only_type0 /* esc */)
{
	return quote_double_only_type1(&o);
}


struct quote_double_only_type2
{
	SQLQueryParms *qparms;
	quote_double_only_type2(SQLQueryParms* p) :
	qparms(p)
	{
	}
};


inline quote_double_only_type2
operator <<(SQLQueryParms& p, quote_double_only_type0 /* esc */)
{
	return quote_double_only_type2(&p);
}


/// \brief Inserts a SQLTypeAdapter into a stream, double-quoting it (")
/// unless it's data that needs no quoting.
///
/// We make the decision to quote the data based on the in.quote_q()
/// flag.  You can set it yourself, but SQLTypeAdapter's ctors should set
/// it correctly for you.

MYSQLPP_EXPORT SQLQueryParms&
operator <<(quote_double_only_type2 p, SQLTypeAdapter& in);


std::ostream&
operator <<(quote_double_only_type1 o, const SQLTypeAdapter& in);


template <class ST>
inline std::ostream&
operator <<(quote_double_only_type1 o, const Set<ST>& in)
{
	return *o.ostr << '"' << in << '"';
}

#endif // !defined(DOXYGEN_IGNORE)


/// \enum escape_type0
/// The 'escape' manipulator.
///
/// SQL-escapes following argument if it is of a data type that
/// may require escaping when inserted into a Query or SQLQueryParms
/// stream.  This is useful with string types, for example, to avoid
/// bad SQL when they contain special characters like single quotes,
/// nulls, and newlines.  Data types like integers which never benefit
/// from escaping don't get run through the escaping routine even if
/// you ask for it.

enum escape_type0 { escape };


#if !defined(DOXYGEN_IGNORE)
// Doxygen will not generate documentation for this section.

struct escape_type1
{
	std::ostream* ostr;
	escape_type1(std::ostream* o) :
	ostr(o)
	{
	}
};


inline escape_type1
operator <<(std::ostream& o, escape_type0 /* esc */)
{
	return escape_type1(&o);
}


struct escape_type2
{
	SQLQueryParms *qparms;
	escape_type2(SQLQueryParms* p) :
	qparms(p)
	{
	}
};


inline escape_type2
operator <<(SQLQueryParms& p, escape_type0 /* esc */)
{
	return escape_type2(&p);
}

#endif // !defined(DOXYGEN_IGNORE)


/// \brief Inserts a SQLTypeAdapter into a stream, escaping special SQL
/// characters
///
/// We actually only do the escaping if in.escape_q() returns true but
/// in.dont_escape is not.  If that is not the case, we insert the
/// string data directly.

MYSQLPP_EXPORT SQLQueryParms& operator <<(escape_type2 p,
		SQLTypeAdapter& in);


/// \brief Inserts anything that can be converted to SQLTypeAdapter into
/// a stream, escaping special SQL characters as needed.

MYSQLPP_EXPORT std::ostream& operator <<(escape_type1 o,
		const SQLTypeAdapter& in);


/// \enum do_nothing_type0
/// \anchor do_nothing_manip
///
/// The 'do_nothing' manipulator.
///
/// Does exactly what it says: nothing. Used as a dummy manipulator when
/// you are required to use some manipulator but don't want anything to
/// be done to the following item. When used with SQLQueryParms it will
/// make sure that it does not get formatted in any way, overriding any
/// setting set by the template query.

enum do_nothing_type0
{
	do_nothing				///< insert into a std::ostream to override manipulation of next item
};


#if !defined(DOXYGEN_IGNORE)
// Doxygen will not generate documentation for this section.

struct do_nothing_type1
{
	std::ostream* ostr;
	do_nothing_type1(std::ostream* o) :
	ostr(o)
	{
	}
};


inline do_nothing_type1
operator <<(std::ostream& o, do_nothing_type0 /* esc */)
{
	return do_nothing_type1(&o);
}


MYSQLPP_EXPORT std::ostream&
operator <<(do_nothing_type1 o, const SQLTypeAdapter& in);


struct do_nothing_type2
{
	SQLQueryParms *qparms;
	do_nothing_type2(SQLQueryParms* p) :
	qparms(p)
	{
	}
};


inline do_nothing_type2
operator <<(SQLQueryParms& p, do_nothing_type0 /* esc */)
{
	return do_nothing_type2(&p);
}


/// \brief Inserts a SQLTypeAdapter into a stream, with no escaping or
/// quoting.

MYSQLPP_EXPORT SQLQueryParms& operator <<(do_nothing_type2 p,
		SQLTypeAdapter& in);

#endif // !defined(DOXYGEN_IGNORE)


/// \enum ignore_type0
/// \anchor ignore_manip
///
/// The 'ignore' manipulator.
///
/// Only valid when used with SQLQueryParms. It's a dummy manipulator
/// like the <a href="#do_nothing_manip">do_nothing manipulator</a>,
/// except that it will not override formatting set by the template
/// query.  It is simply ignored.

enum ignore_type0
{
	ignore					///< insert into a std::ostream as a dummy manipulator
};


#if !defined(DOXYGEN_IGNORE)
// Doxygen will not generate documentation for this section.

struct ignore_type2
{
	SQLQueryParms* qparms;
	ignore_type2(SQLQueryParms* p) :
	qparms(p)
	{
	}
};


inline ignore_type2
operator <<(SQLQueryParms& p, ignore_type0 /* esc */)
{
	return ignore_type2(&p);
}


/// \brief Inserts a SQLTypeAdapter into a stream, with no escaping or
/// quoting, and without marking the string as having been "processed".

MYSQLPP_EXPORT SQLQueryParms& operator <<(ignore_type2 p,
		SQLTypeAdapter& in);

#endif // !defined(DOXYGEN_IGNORE)

} // end namespace mysqlpp

#endif

Changes to examples/vstudio/wforms/AssemblyInfo.cpp.























































1
2





























































































































































































































3


4















5


















































































































































































































































































































































































































































































































































































































































































































































6





7













8




9


10


11


12


13



14


15


16


17


18




































































using namespace System;
using namespace System::Reflection;





























































































































































































































using namespace System::Runtime::CompilerServices;


using namespace System::Runtime::InteropServices;















using namespace System::Security::Permissions;
























































































































































































































































































































































































































































































































































































































































































































































[assembly:AssemblyTitleAttribute("wforms")];













[assembly:AssemblyDescriptionAttribute("")];




[assembly:AssemblyConfigurationAttribute("")];


[assembly:AssemblyCompanyAttribute("the MySQL++ project")];


[assembly:AssemblyProductAttribute("MySQL++ Windows Forms Example")];


[assembly:AssemblyCopyrightAttribute("Copyright © 2007 by ETR, Inc.")];


[assembly:AssemblyTrademarkAttribute("")];



[assembly:AssemblyCultureAttribute("")];


[assembly:AssemblyVersionAttribute("1.0.*")];


[assembly:ComVisible(false)];


[assembly:CLSCompliantAttribute(true)];


[assembly:SecurityPermission(SecurityAction::RequestMinimum, UnmanagedCode = true)];














>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
>
>
>
|
>
>
|
>
>
|
>
>
|
>
>
|
>
>
>
|
>
>
|
>
>
|
>
>
|
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
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
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
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
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
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
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
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
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
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
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
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
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
/// \file query.h
/// \brief Defines a class for building and executing SQL queries.

/***********************************************************************
 Copyright (c) 1998 by Kevin Atkinson, (c) 1999-2001 by MySQL AB, and
 (c) 2004-2008 by Educational Technology Resources, Inc.  Others may
 also hold copyrights on code in this file.  See the CREDITS file in
 the top directory of the distribution for details.

 This file is part of MySQL++.

 MySQL++ is free software; you can redistribute it and/or modify it
 under the terms of the GNU Lesser General Public License as published
 by the Free Software Foundation; either version 2.1 of the License, or
 (at your option) any later version.

 MySQL++ is distributed in the hope that it will be useful, but WITHOUT
 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
 License for more details.

 You should have received a copy of the GNU Lesser General Public
 License along with MySQL++; if not, write to the Free Software
 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
 USA
***********************************************************************/

#if !defined(MYSQLPP_QUERY_H)
#define MYSQLPP_QUERY_H

#include "common.h"

#include "noexceptions.h"
#include "qparms.h"
#include "querydef.h"
#include "result.h"
#include "row.h"
#include "stadapter.h"

#include <deque>
#include <iomanip>
#include <list>
#include <map>
#include <set>
#include <vector>

#ifdef HAVE_EXT_SLIST
#  include <ext/slist>
#else
#  if defined(HAVE_STD_SLIST) || defined(HAVE_GLOBAL_SLIST)
#      include <slist>
#  endif
#endif

namespace mysqlpp {

#if !defined(DOXYGEN_IGNORE)
// Make Doxygen ignore this
class MYSQLPP_EXPORT Connection;
#endif

/// \brief A class for building and executing SQL queries.
///
/// One does not generally create Query objects directly. Instead, call
/// mysqlpp::Connection::query() to get one tied to that connection.
///
/// There are several ways to build and execute SQL queries with this
/// class.
///
/// The way most like other database libraries is to pass a SQL
/// statement in either the form of a C or C++ string to one of the
/// \link mysqlpp::Query::execute() exec*(), \endlink
/// \link mysqlpp::Query::store() store*(), \endlink or use() methods.
/// The query is executed immediately, and any results returned.
///
/// For more complicated queries, it's often more convenient to build up
/// the query string over several C++ statements using Query's stream
/// interface. It works like any other C++ stream (\c std::cout,
/// \c std::ostringstream, etc.) in that you can just insert things
/// into the stream, building the query up piece by piece. When the
/// query string is complete, you  call the overloaded version of
/// \link mysqlpp::Query::execute() exec*(), \endlink
/// \link mysqlpp::Query::store() store*(), \endlink or
/// \link mysqlpp::Query::use() use() \endlink takes no parameters,
/// which executes the built query and returns any results.
///
/// If you are using the library's Specialized SQL Structures feature,
/// Query has several special functions for generating common SQL
/// queries from those structures. For instance, it offers the
/// \link mysqlpp::Query::insert() insert() \endlink method, which
/// builds an INSERT query to add the contents of the SSQLS to the
/// database. As with the stream interface, these methods only build
/// the query string; call one of the parameterless methods mentioned
/// previously to actually execute the query.
///
/// Finally, you can build "template queries". This is something like
/// C's \c printf() function, in that you insert a specially-formatted
/// query string into the object which contains placeholders for data.
/// You call the parse() method to tell the Query object that the query
/// string contains placeholders. Having done that, you call one of the
/// the many
/// \link mysqlpp::Query::execute(const SQLTypeAdapter&) exec*(), \endlink
/// \link mysqlpp::Query::store(const SQLTypeAdapter&) store*(), \endlink
/// or \link mysqlpp::Query::use(const SQLTypeAdapter&) use() \endlink
/// overloads that take SQLTypeAdapter objects.  There are 25 of each by
/// default, differing only in the number of STA objects they take.
/// (See \c lib/querydef.pl if you need to change the limit, or 
/// \c examples/tquery2.cpp for a way around it that doesn't require 
/// changing the library.)  Only the version taking a single STA object
/// is documented below, as to document all of them would just be
/// repetitive.  For each Query method that takes a single STA object,
/// there's a good chance there's a set of undocumented overloads that
/// take more of them for the purpose of filling out a template query.
///
/// See the user manual for more details about these options.

class MYSQLPP_EXPORT Query :
        public std::ostream,
		public OptionalExceptions
{
private:
	/// \brief Pointer to bool data member, for use by safe bool
	/// conversion operator.
	///
	/// \see http://www.artima.com/cppsource/safebool.html
    typedef bool Query::*private_bool_type;

public:
	/// \brief Create a new query object attached to a connection.
	///
	/// This is the constructor used by mysqlpp::Connection::query().
	///
	/// \param c connection the finished query should be sent out on
	/// \param te if true, throw exceptions on errors
	/// \param qstr an optional initial query string
	Query(Connection* c, bool te = true, const char* qstr = 0);

	/// \brief Create a new query object as a copy of another.
	///
	/// This is \b not a traditional copy ctor!  Its only purpose is to
	/// make it possible to assign the return of Connection::query()
	/// to an empty Query object.  In particular, the stream buffer and
	/// template query stuff will be empty in the copy, regardless of
	/// what values they have in the original.
	Query(const Query& q);

	/// \brief Return the number of rows affected by the last query
	ulonglong affected_rows();

	/// \brief Return a SQL-escaped version of a character buffer
	///
	/// \param ps pointer to C++ string to hold escaped version; if
	/// original is 0, also holds the original data to be escaped
	/// \param original if given, pointer to the character buffer to
	/// escape instead of contents of *ps
	/// \param length if both this and original are given, number of
	/// characters to escape instead of ps->length()
	///
	/// \retval number of characters placed in *ps
	///
	/// This method has three basic operation modes:
	///
	/// - Pass just a pointer to a C++ string containing the original
	///   data to escape, plus act as receptacle for escaped version
	/// - Pass a pointer to a C++ string to receive escaped string plus
	///   a pointer to a C string to be escaped
	/// - Pass nonzero for all parameters, taking original to be a
	///   pointer to an array of char with given length; does not treat
	///   null characters as special
	///
	/// There's a degenerate fourth mode, where ps is zero: simply
	/// returns 0, because there is nowhere to store the result.
	///
	/// Note that if original is 0, we always ignore the length
	/// parameter even if it is nonzero.  Length always comes from
	/// ps->length() in this case.
	///
	/// ps is a pointer because if it were a reference, the other
	/// overload would be impossible to call: the compiler would
	/// complain that the two overloads are ambiguous because
	/// std::string has a char* conversion ctor. A nice bonus is that
	/// pointer syntax makes it clearer that the first parameter is an
	/// "out" parameter.
	///
	/// \see comments for escape_string(char*, const char*, size_t)
	/// for further details.
	size_t escape_string(std::string* ps, const char* original = 0,
			size_t length = 0) const;

	/// \brief Return a SQL-escaped version of the given character
	/// buffer
	///
	/// \param escaped character buffer to hold escaped version; must
	/// point to at least (length * 2 + 1) bytes
	/// \param original pointer to the character buffer to escape
	/// \param length number of characters to escape
	///
	/// \retval number of characters placed in escaped
	///
	/// This is part of Query because proper SQL escaping takes the
	/// database's current character set into account, which requires
	/// access to the Connection object the query will go out on.  Also,
	/// this function is very important to MySQL++'s Query stream
	/// manipulator mechanism, so it's more convenient for this method
	/// to live in Query rather than Connection.
	size_t escape_string(char* escaped, const char* original,
			size_t length) const;

	/// \brief Get the last error number that was set.
	///
	/// This just delegates to Connection::errnum().  Query has nothing
	/// extra to say, so use either, as makes sense in your program.
	int errnum() const;

	/// \brief Get the last error message that was set.
	///
	/// This just delegates to Connection::error().  Query has nothing
	/// extra to say, so use either, as makes sense in your program.
	const char* error() const;

	/// \brief Returns information about the most recently executed
	/// query.
	std::string info();

	/// \brief Get ID generated for an AUTO_INCREMENT column in the
	/// previous INSERT query.
	///
	/// \retval 0 if the previous query did not generate an ID.  Use
	/// the SQL function LAST_INSERT_ID() if you need the last ID
	/// generated by any query, not just the previous one.
	ulonglong insert_id();

	/// \brief Assign another query's state to this object
	///
	/// The same caveats apply to this operator as apply to the copy
	/// ctor.
	Query& operator=(const Query& rhs);

	/// \brief Test whether the object has experienced an error condition
	///
	/// Allows for code constructs like this:
	///
	/// \code
	///	Query q = conn.query();
	///	.... use query object
	///	if (q) {
	///	    ... no problems in using query object
	///	}
	///	else {
	///	    ... an error has occurred
	///	}
	/// \endcode
	///
	/// This method returns false if either the Query object or its
	/// associated Connection object has seen an error condition since
	/// the last operation.
	operator private_bool_type() const;

	/// \brief Treat the contents of the query string as a template
	/// query.
	///
	/// This method sets up the internal structures used by all of the
	/// other members that accept template query parameters.  See the
	/// "Template Queries" chapter in the user manual for more
	/// information.
	void parse();

	/// \brief Reset the query object so that it can be reused.
	///
	/// As of v3.0, Query objects auto-reset upon query execution unless
	/// you've set it up for making template queries.  (It can't auto-reset
	/// in that situation, because it would forget the template info.)
	/// Therefore, the only time you must call this is if you have a Query
	/// object set up for making template queries, then want to build
	/// queries using one of the other methods.  (Static strings, SSQLS,
	/// or the stream interface.)
	void reset();

	/// \brief Get built query as a C++ string
	std::string str() { return str(template_defaults); }

	/// \brief Get built query as a C++ string with template query
	/// parameter substitution.
	///
	/// \param arg0 the value to substitute for the first template query
	/// parameter; because SQLTypeAdapter implicitly converts from many
	/// different data types, this method is very flexible in what it
	/// accepts as a parameter.  You shouldn't have to use the
	/// SQLTypeAdapter data type directly in your code.
	///
	/// There many more overloads of this type (25 total, by default;
	/// see \c lib/querydef.pl), each taking one more SQLTypeAdapter object
	/// than the previous one.  See the template query overview above
	/// for more about this topic.
	std::string str(const SQLTypeAdapter& arg0)
			{ return str(SQLQueryParms() << arg0); }

	/// \brief Get built query as a null-terminated C++ string
	///
	/// \param p template query parameters to use, overriding the ones
	/// this object holds, if any
	std::string str(SQLQueryParms& p);

	/// \brief Execute a built-up query
	///
	/// Same as exec(), except that it uses the query string built up
	/// within the query object already instead of accepting a query
	/// string from the caller.
	///
	/// \return true if query was executed successfully
	///
	/// \sa exec(const std::string& str), execute(), store(),
	/// storein(), and use()
	bool exec() { return exec(str(template_defaults)); }

	/// \brief Execute a query
	///
	/// Same as execute(), except that it only returns a flag indicating
	/// whether the query succeeded or not.  It is basically a thin
	/// wrapper around the C API function \c mysql_real_query().
	///
	/// \param str the query to execute
	///
	/// \return true if query was executed successfully
	///
	/// \sa execute(), store(), storein(), and use()
	bool exec(const std::string& str);

	/// \brief Execute built-up query
	///
	/// Use one of the execute() overloads if you don't expect the
	/// server to return a result set. For instance, a DELETE query.
	/// The returned SimpleResult object contains status information from
	/// the server, such as whether the query succeeded, and if so how
	/// many rows were affected.
	///
	/// This overloaded version of execute() simply executes the query
	/// that you have built up in the object in some way. (For instance,
	/// via the insert() method, or by using the object's stream
	/// interface.)
	///
	/// \return SimpleResult status information about the query
	///
	/// \sa exec(), store(), storein(), and use()
	SimpleResult execute() { return execute(str(template_defaults)); }

	/// \brief Execute template query using given parameters.
    ///
    /// This method should only be used by code that doesn't know,
    /// at compile time, how many parameters it will have.  This is
    /// useful within the library, and also for code that builds
    /// template queries dynamically, at run time.
	///
	/// \param p parameters to use in the template query.
	SimpleResult execute(SQLQueryParms& p);

	/// \brief Execute a query that returns no rows
	///
	/// \param str if this object is set up as a template query, this is
	/// the value to substitute for the first template query parameter;
	/// else, it is the SQL query string to execute
	///
	/// Because SQLTypeAdapter can be initialized from either a C string
	/// or a C++ string, this overload accepts query strings in either
	/// form.  Beware, SQLTypeAdapter also accepts many other data types
	/// (this is its \e raison \e d'etre), so it will let you write code
	/// that compiles but results in bogus SQL queries.
	///
	/// To support template queries, there many more overloads of this
	/// type (25 total, by default; see \c lib/querydef.pl), each taking
	/// one more SQLTypeAdapter object than the previous one.  See the
	/// template query overview above for more about this topic.
	SimpleResult execute(const SQLTypeAdapter& str);

	/// \brief Execute query in a known-length string of characters.
	/// This can include null characters.
	///
	/// Executes the query immediately, and returns the results.
	SimpleResult execute(const char* str, size_t len);

	/// \brief Execute a query that can return rows, with access to
	/// the rows in sequence
	/// 
	/// Use one of the use() overloads if memory efficiency is
	/// important.  They return an object that can walk through
	/// the result records one by one, without fetching the entire
	/// result set from the server.  This is superior to store()
	/// when there are a large number of results; store() would have to
	/// allocate a large block of memory to hold all those records,
	/// which could cause problems.
	///
	/// A potential downside of this method is that MySQL database
	/// resources are tied up until the result set is completely
	/// consumed.  Do your best to walk through the result set as
	/// expeditiously as possible.
	///
	/// The name of this method comes from the MySQL C API function
	/// that initiates the retrieval process, \c mysql_use_result().
	/// This method is implemented in terms of that function.
	///
	/// This function has the same set of overloads as execute().
	///
	/// \return UseQueryResult object that can walk through result set serially
	///
	/// \sa exec(), execute(), store() and storein()
	UseQueryResult use() { return use(str(template_defaults)); }

	/// \brief Execute a template query that can return rows, with
	/// access to the rows in sequence
    ///
    /// This method should only be used by code that doesn't know,
    /// at compile time, how many parameters it will have.  This is
    /// useful within the library, and also for code that builds
    /// template queries dynamically, at run time.
	///
	/// \param p parameters to use in the template query.
	UseQueryResult use(SQLQueryParms& p);

	/// \brief Execute a query that can return rows, with access to
	/// the rows in sequence
	///
	/// \param str if this object is set up as a template query, this is
	/// the value to substitute for the first template query parameter;
	/// else, it is the SQL query string to execute
	///
	/// Because SQLTypeAdapter can be initialized from either a C string
	/// or a C++ string, this overload accepts query strings in either
	/// form.  Beware, SQLTypeAdapter also accepts many other data types
	/// (this is its \e raison \e d'etre), so it will let you write code
	/// that compiles but results in bogus SQL queries.
	///
	/// To support template queries, there many more overloads of this
	/// type (25 total, by default; see \c lib/querydef.pl), each taking
	/// one more SQLTypeAdapter object than the previous one.  See the
	/// template query overview above for more about this topic.
	UseQueryResult use(const SQLTypeAdapter& str);

	/// \brief Execute a query that can return rows, with access to
	/// the rows in sequence
	///
	/// This overload is for situations where you have the query in a
	/// C string and have its length already.  If you want to execute
	/// a query in a null-terminated C string or have the query string
	/// in some other form, you probably want to call
	/// use(const SQLTypeAdapter&) instead.  SQLTypeAdapter converts
	/// from plain C strings and other useful data types implicitly.
	UseQueryResult use(const char* str, size_t len);

	/// \brief Execute a query that can return a result set
	///
	/// Use one of the store() overloads to execute a query and retrieve
	/// the entire result set into memory.  This is useful if you
	/// actually need all of the records at once, but if not, consider
	/// using one of the use() methods instead, which returns the results
	/// one at a time, so they don't allocate as much memory as store().
	///
	/// You must use store(), storein() or use() for \c SELECT, \c SHOW,
	/// \c DESCRIBE and \c EXPLAIN queries.  You can use these functions
	/// with other query types, but since they don't return a result
	/// set, exec() and execute() are more efficient.
	///
	/// The name of this method comes from the MySQL C API function it
	/// is implemented in terms of, \c mysql_store_result().
	///
	/// This function has the same set of overloads as execute().
	///
	/// \return StoreQueryResult object containing entire result set
	///
	/// \sa exec(), execute(), storein(), and use()
	StoreQueryResult store() { return store(str(template_defaults)); }

	/// \brief Store results from a template query using given parameters.
    ///
    /// This method should only be used by code that doesn't know,
    /// at compile time, how many parameters it will have.  This is
    /// useful within the library, and also for code that builds
    /// template queries dynamically, at run time.
	///
	/// \param p parameters to use in the template query.
	StoreQueryResult store(SQLQueryParms& p);

	/// \brief Execute a query that can return rows, returning all
	/// of the rows in a random-access container
	///
	/// \param str if this object is set up as a template query, this is
	/// the value to substitute for the first template query parameter;
	/// else, it is the SQL query string to execute
	///
	/// Because SQLTypeAdapter can be initialized from either a C string
	/// or a C++ string, this overload accepts query strings in either
	/// form.  Beware, SQLTypeAdapter also accepts many other data types
	/// (this is its \e raison \e d'etre), so it will let you write code
	/// that compiles but results in bogus SQL queries.
	///
	/// To support template queries, there many more overloads of this
	/// type (25 total, by default; see \c lib/querydef.pl), each taking
	/// one more SQLTypeAdapter object than the previous one.  See the
	/// template query overview above for more about this topic.
	StoreQueryResult store(const SQLTypeAdapter& str);

	/// \brief Execute a query that can return rows, returning all
	/// of the rows in a random-access container
	///
	/// This overload is for situations where you have the query in a
	/// C string and have its length already.  If you want to execute
	/// a query in a null-terminated C string or have the query string
	/// in some other form, you probably want to call
	/// store(const SQLTypeAdapter&) instead.  SQLTypeAdapter converts
	/// from plain C strings and other useful data types implicitly.
	StoreQueryResult store(const char* str, size_t len);

	/// \brief Execute a query, and call a functor for each returned row
	///
	/// This method wraps a use() query, calling the given functor for
	/// every returned row.  It is analogous to STL's for_each()
	/// algorithm, but instead of iterating over some range within a
	/// container, it iterates over a result set produced by a query.
	///
	/// \param query the query string
	/// \param fn the functor called for each row
	/// \return a copy of the passed functor
	template <typename Function>
	Function for_each(const SQLTypeAdapter& query, Function fn)
	{	
		mysqlpp::UseQueryResult res = use(query);
		if (res) {
			mysqlpp::NoExceptions ne(res);
			while (mysqlpp::Row row = res.fetch_row()) {
				fn(row);
			}
		}

		return fn;
	}

	/// \brief Execute the query, and call a functor for each returned row
	///
	/// Just like for_each(const SQLTypeAdapter&, Function), but it uses
	/// the query string held by the Query object already
	///
	/// \param fn the functor called for each row
	/// \return a copy of the passed functor
	template <typename Function>
	Function for_each(Function fn)
	{	
		mysqlpp::UseQueryResult res = use();
		if (res) {
			mysqlpp::NoExceptions ne(res);
			while (mysqlpp::Row row = res.fetch_row()) {
				fn(row);
			}
		}

		return fn;
	}

	/// \brief Run a functor for every row in a table
	///
	/// Just like for_each(Function), except that it builds a
	/// "select * from TABLE" query using the SQL table name from
	/// the SSQLS instance you pass.
	///
	/// \param ssqls the SSQLS instance to get a table name from
	/// \param fn the functor called for each row
	///
	/// \return a copy of the passed functor
	template <class SSQLS, typename Function>
	Function for_each(const SSQLS& ssqls, Function fn)
	{	
		std::string query("select * from ");
		query += ssqls.table();
		mysqlpp::UseQueryResult res = use(query);
		if (res) {
			mysqlpp::NoExceptions ne(res);
			while (mysqlpp::Row row = res.fetch_row()) {
				fn(row);
			}
		}

		return fn;
	}

	/// \brief Execute a query, conditionally storing each row in a
	/// container
	///
	/// This method wraps a use() query, calling the given functor for
	/// every returned row, and storing the results in the given
	/// sequence container if the functor returns true.
	///
	/// This is analogous to the STL copy_if() algorithm, except that
	/// the source rows come from a database query instead of another
	/// container.  (copy_if() isn't a standard STL algorithm, but only
	/// due to an oversight by the standardization committee.)  This
	/// fact may help you to remember the order of the parameters: the
	/// container is the destination, the query is the source, and the
	/// functor is the predicate; it's just like an STL algorithm.
	///
	/// \param con the destination container; needs a push_back() method
	/// \param query the query string
	/// \param fn the functor called for each row
	/// \return a copy of the passed functor
	template <class Sequence, typename Function>
	Function store_if(Sequence& con, const SQLTypeAdapter& query, Function fn)
	{	
		mysqlpp::UseQueryResult res = use(query);
		if (res) {
			mysqlpp::NoExceptions ne(res);
			while (mysqlpp::Row row = res.fetch_row()) {
				if (fn(row)) {
					con.push_back(row);
				}
			}
		}

		return fn;
	}

	/// \brief Pulls every row in a table, conditionally storing each
	/// one in a container
	///
	/// Just like store_if(Sequence&, const SQLTypeAdapter&, Function), but
	/// it uses the SSQLS instance to construct a "select * from TABLE"
	/// query, using the table name field in the SSQLS.
	///
	/// \param con the destination container; needs a push_back() method
	/// \param ssqls the SSQLS instance to get a table name from
	/// \param fn the functor called for each row
	/// \return a copy of the passed functor
	template <class Sequence, class SSQLS, typename Function>
	Function store_if(Sequence& con, const SSQLS& ssqls, Function fn)
	{	
		std::string query("select * from ");
		query += ssqls.table();
		mysqlpp::UseQueryResult res = use(query);
		if (res) {
			mysqlpp::NoExceptions ne(res);
			while (mysqlpp::Row row = res.fetch_row()) {
				if (fn(row)) {
					con.push_back(row);
				}
			}
		}

		return fn;
	}

	/// \brief Execute the query, conditionally storing each row in a
	/// container
	///
	/// Just like store_if(Sequence&, const SQLTypeAdapter&, Function), but
	/// it uses the query string held by the Query object already
	///
	/// \param con the destination container; needs a push_back() method
	/// \param fn the functor called for each row
	/// \return a copy of the passed functor
	template <class Sequence, typename Function>
	Function store_if(Sequence& con, Function fn)
	{	
		mysqlpp::UseQueryResult res = use();
		if (res) {
			mysqlpp::NoExceptions ne(res);
			while (mysqlpp::Row row = res.fetch_row()) {
				if (fn(row)) {
					con.push_back(row);
				}
			}
		}

		return fn;
	}

	/// \brief Return next result set, when processing a multi-query
	///
	/// There are two cases where you'd use this function instead of
	/// the regular store() functions.
	/// 
	/// First, when handling the result of executing multiple queries
	/// at once.  (See <a
	/// href="http://dev.mysql.com/doc/mysql/en/c-api-multiple-queries.html">this
	/// page</a> in the MySQL documentation for details.) 
	///
	/// Second, when calling a stored procedure, MySQL can return the
	/// result as a set of results.
	///
	/// In either case, you must consume all results before making
	/// another MySQL query, even if you don't care about the remaining
	/// results or result sets.
	///
	/// As the MySQL documentation points out, you must set the
	/// MYSQL_OPTION_MULTI_STATEMENTS_ON flag on the connection in order
	/// to use this feature.  See Connection::set_option().
	///
	/// Multi-queries only exist in MySQL v4.1 and higher.  Therefore,
	/// this function just wraps store() when built against older API
	/// libraries.
	///
	/// \return StoreQueryResult object containing the next result set.
	StoreQueryResult store_next();

	/// \brief Return whether more results are waiting for a multi-query
	/// or stored procedure response.
	///
	/// If this function returns true, you must call store_next() to
	/// fetch the next result set before you can execute more queries.
	///
	/// Wraps mysql_more_results() in the MySQL C API.  That function
	/// only exists in MySQL v4.1 and higher.  Therefore, this function
	/// always returns false when built against older API libraries.
	///
	/// \return true if another result set exists
	bool more_results();

	/// \brief Execute a query, storing the result set in an STL
	/// sequence container.
	///
	/// This function works much like store() from the caller's
	/// perspective, because it returns the entire result set at once.
	/// It's actually implemented in terms of use(), however, so that
	/// memory for the result set doesn't need to be allocated twice.
	///
	/// There are many overloads for this function, pretty much the same
	/// as for execute(), except that there is a Container parameter at
	/// the front of the list.  So, you can pass a container and a query
	/// string, or a container and template query parameters.
	///
	/// \param con any STL sequence container, such as \c std::vector
	///
	/// \sa exec(), execute(), store(), and use()
	template <class Sequence>
	void storein_sequence(Sequence& con)
	{
		storein_sequence(con, str(template_defaults));
	}

	/// \brief Executes a query, storing the result rows in an STL
	/// sequence container.
	///
	/// \param con the container to store the results in
	///
	/// \param s if Query is set up as a template query, this is the value
	/// to substitute for the first template query parameter; else, the
	/// SQL query string
	///
	/// There many more overloads of this type (25 total, by default;
	/// see \c lib/querydef.pl), each taking one more SQLTypeAdapter object
	/// than the previous one.  See the template query overview above
	/// for more about this topic.
	template <class Sequence>
	void storein_sequence(Sequence& con, const SQLTypeAdapter& s)
	{
		UseQueryResult result = use(s);
		while (1) {
			MYSQL_ROW d = result.fetch_raw_row();
			if (!d)
				break;
			Row row(d, &result, result.fetch_lengths(), true);
			if (!row)
				break;
			con.push_back(typename Sequence::value_type(row));
		}
	}

	/// \brief Execute template query using given parameters, storing
    /// the results in a sequence type container.
    ///
    /// This method should only be used by code that doesn't know,
    /// at compile time, how many parameters it will have.  This is
    /// useful within the library, and also for code that builds
    /// template queries dynamically, at run time.
	///
	/// \param con container that will receive the results
	/// \param p parameters to use in the template query.
    template <class Seq>
    void storein_sequence(Seq& con, SQLQueryParms& p)
    {
        storein_sequence(con, str(p));
    }

	/// \brief Execute a query, storing the result set in an STL
	/// associative container.
	///
	/// The same thing as storein_sequence(), except that it's used with
	/// associative STL containers, such as \c std::set.  Other than
	/// that detail, that method's comments apply equally well to this
	/// one.
	template <class Set>
	void storein_set(Set& con)
	{
		storein_set(con, str(template_defaults));
	}

	/// \brief Executes a query, storing the result rows in an STL
	/// set-associative container.
	///
	/// \param con the container to store the results in
	///
	/// \param s if Query is set up as a template query, this is the value
	/// to substitute for the first template query parameter; else, the
	/// SQL query string
	///
	/// There many more overloads of this type (25 total, by default;
	/// see \c lib/querydef.pl), each taking one more SQLTypeAdapter object
	/// than the previous one.  See the template query overview above
	/// for more about this topic.
	template <class Set>
	void storein_set(Set& con, const SQLTypeAdapter& s)
	{
		UseQueryResult result = use(s);
		while (1) {
			MYSQL_ROW d = result.fetch_raw_row();
			if (!d)
				return;
			Row row(d, &result, result.fetch_lengths(), true);
			if (!row)
				break;
			con.insert(typename Set::value_type(row));
		}
	}

	/// \brief Execute template query using given parameters, storing
    /// the results in a set type container.
    ///
    /// This method should only be used by code that doesn't know,
    /// at compile time, how many parameters it will have.  This is
    /// useful within the library, and also for code that builds
    /// template queries dynamically, at run time.
	///
	/// \param con container that will receive the results
	/// \param p parameters to use in the template query.
    template <class Set>
    void storein_set(Set& con, SQLQueryParms& p)
    {
        storein_set(con, str(p));
    }

	/// \brief Execute a query, and store the entire result set
	/// in an STL container.
	///
	/// This is a set of specialized template functions that call either
	/// storein_sequence() or storein_set(), depending on the type of
	/// container you pass it. It understands \c std::vector, \c deque,
	/// \c list, \c slist (a common C++ library extension), \c set,
	/// and \c multiset.
	///
	/// Like the functions it wraps, this is actually an overloaded set
	/// of functions. See the other functions' documentation for details.
	///
	/// Use this function if you think you might someday switch your
	/// program from using a set-associative container to a sequence
	/// container for storing result sets, or vice versa.
	///
	/// See exec(), execute(), store(), and use() for alternative
	/// query execution mechanisms.
	template <class Container>
	void storein(Container& con)
	{
		storein(con, str(template_defaults));
	}

	/// \brief Specialization of storein_sequence() for \c std::vector
	template <class T>
	void storein(std::vector<T>& con, const SQLTypeAdapter& s)
	{
		storein_sequence(con, s);
	}

	/// \brief Specialization of storein_sequence() for \c std::deque
	template <class T>
	void storein(std::deque<T>& con, const SQLTypeAdapter& s)
	{
		storein_sequence(con, s);
	}

	/// \brief Specialization of storein_sequence() for \c std::list
	template <class T>
	void storein(std::list<T>& con, const SQLTypeAdapter& s)
	{
		storein_sequence(con, s);
	}

#if defined(HAVE_EXT_SLIST)
	/// \brief Specialization of storein_sequence() for g++ STL
	/// extension \c slist
	template <class T>
	void storein(__gnu_cxx::slist<T>& con, const SQLTypeAdapter& s)
	{
		storein_sequence(con, s);
	}
#elif defined(HAVE_GLOBAL_SLIST)
	/// \brief Specialization of storein_sequence() for STL
	/// extension \c slist
	///
	/// This is primarily for older versions of g++, which put \c slist
	/// in the global namespace.  This is a common language extension,
	/// so this may also work for other compilers.
	template <class T>
	void storein(slist<T>& con, const SQLTypeAdapter& s)
	{
		storein_sequence(con, s);
	}
#elif defined(HAVE_STD_SLIST)
	/// \brief Specialization of storein_sequence() for STL
	/// extension \c slist
	///
	/// This is for those benighted compilers that include an \c slist
	/// implementation, but erroneously put it in the \c std namespace!
	template <class T>
	void storein(std::slist<T>& con, const SQLTypeAdapter& s)
	{
		storein_sequence(con, s);
	}
#endif

	/// \brief Specialization of storein_set() for \c std::set
	template <class T>
	void storein(std::set<T>& con, const SQLTypeAdapter& s)
	{
		storein_set(con, s);
	}

	/// \brief Specialization of storein_set() for \c std::multiset
	template <class T>
	void storein(std::multiset<T>& con, const SQLTypeAdapter& s)
	{
		storein_set(con, s);
	}

	/// \brief Replace an existing row's data with new data.
	///
	/// This function builds an UPDATE SQL query using the new row data
	/// for the SET clause, and the old row data for the WHERE clause.
	/// One uses it with MySQL++'s Specialized SQL Structures mechanism.
	///
	/// \param o old row
	/// \param n new row
	///
	/// \sa insert(), replace()
	template <class T>
	Query& update(const T& o, const T& n)
	{
		reset();

		// Cast required for VC++ 2003 due to error in overloaded operator
		// lookup logic.  For an explanation of the problem, see:
		// http://groups-beta.google.com/group/microsoft.public.vc.stl/browse_thread/thread/9a68d84644e64f15
		MYSQLPP_QUERY_THISPTR << std::setprecision(16) <<
				"UPDATE " << o.table() << " SET " << n.equal_list() <<
				" WHERE " << o.equal_list(" AND ", sql_use_compare);
		return *this;
	}

	/// \brief Insert a new row.
	///
	/// This function builds an INSERT SQL query.  One uses it with
	/// MySQL++'s Specialized SQL Structures mechanism.
	///
	/// \param v new row
	///
	/// \sa replace(), update()
	template <class T>
	Query& insert(const T& v)
	{
		reset();

		MYSQLPP_QUERY_THISPTR << std::setprecision(16) <<
				"INSERT INTO " << v.table() << " (" <<
				v.field_list() << ") VALUES (" <<
				v.value_list() << ')';
		return *this;
	}

	/// \brief Insert multiple new rows.
	///
	/// Builds an INSERT SQL query using items from a range within an
	/// STL container.  Insert the entire contents of the container by
	/// using the begin() and end() iterators of the container as
	/// parameters to this function.
	///
	/// \param first iterator pointing to first element in range to
	///    insert
	/// \param last iterator pointing to one past the last element to
	///    insert
	///
	/// \sa replace(), update()
	template <class Iter>
	Query& insert(Iter first, Iter last)
	{
		reset();
		if (first == last) {
			return *this;	// empty set!
		}
		
		MYSQLPP_QUERY_THISPTR << std::setprecision(16) <<
				"INSERT INTO " << first->table() << " (" <<
				first->field_list() << ") VALUES (" <<
				first->value_list() << ')';

		Iter it = first + 1;
		while (it != last) {
			MYSQLPP_QUERY_THISPTR << ",(" << it->value_list() << ')';
			++it;
		}

		return *this;
	}

	/// \brief Insert new row unless there is an existing row that
	/// matches on a unique index, in which case we replace it.
	///
	/// This function builds a REPLACE SQL query.  One uses it with
	/// MySQL++'s Specialized SQL Structures mechanism.
	///
	/// \param v new row
	///
	/// \sa insert(), update()
	template <class T>
	Query& replace(const T& v)
	{
		reset();

		MYSQLPP_QUERY_THISPTR << std::setprecision(16) <<
				"REPLACE INTO " << v.table() << " (" <<
				v.field_list() << ") VALUES (" << v.value_list() << ')';
		return *this;
	}

#if !defined(DOXYGEN_IGNORE)
	// Declare the remaining overloads.  These are hidden down here partly
	// to keep the above code clear, but also so that we may hide them
	// from Doxygen, which gets confused by macro instantiations that look
	// like method declarations.
	mysql_query_define0(std::string, str)
	mysql_query_define0(SimpleResult, execute)
	mysql_query_define0(StoreQueryResult, store)
	mysql_query_define0(UseQueryResult, use)
	mysql_query_define1(storein_sequence)
	mysql_query_define1(storein_set)
	mysql_query_define1(storein)
#endif // !defined(DOXYGEN_IGNORE)

	/// \brief The default template parameters
	///
	/// Used for filling in parameterized queries.
	SQLQueryParms template_defaults;

private:
	friend class SQLQueryParms;

	/// \brief Connection to send queries through
	Connection* conn_;

	/// \brief If true, last query succeeded
	bool copacetic_;

	/// \brief List of template query parameters
	std::vector<SQLParseElement> parse_elems_;

	/// \brief Maps template parameter position values to the
	/// corresponding parameter name.
	std::vector<std::string> parsed_names_;

	/// \brief Maps template parameter names to their position value.
	std::map<std::string, short int> parsed_nums_;

	/// \brief String buffer for storing assembled query
	std::stringbuf sbuffer_;

	/// \brief Process a parameterized query list.
	void proc(SQLQueryParms& p);

	SQLTypeAdapter* pprepare(char option, SQLTypeAdapter& S, bool replace = true);
};


/// \brief Insert raw query string into the given stream.
///
/// This is just syntactic sugar for Query::str(void)
inline std::ostream& operator <<(std::ostream& os, Query& q)
{
	return os << q.str();
}


} // end namespace mysqlpp

#endif // !defined(MYSQLPP_QUERY_H)

Changes to examples/vstudio/wforms/MainForm.h.

1
2
3



4

5

6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27

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
56
57
58
59
60
61
62
63
64
65
66
67
68



69

70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102


103
104
105
106
107
108

109
110
111
112
113
114
115
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
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
191
192
193
194
195
196
197
198

199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221


222
223
224
225
226

227
228
229
230
231
232
233
234
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
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
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
336
337
338
339
340

341




342
343
344
345
/***********************************************************************
 MainForm.cpp - Defines the dialog box behavior for the MySQL++ C++/CLI
	Windows Forms example.





 Copyright (c) 2007 by Educational Technology Resources, Inc.  Others 

 may also hold copyrights on code in this file.  See the CREDITS.txt
 file in the top directory of the distribution for details.

 This file is part of MySQL++.

 MySQL++ is free software; you can redistribute it and/or modify it
 under the terms of the GNU Lesser General Public License as published
 by the Free Software Foundation; either version 2.1 of the License, or
 (at your option) any later version.

 MySQL++ is distributed in the hope that it will be useful, but WITHOUT
 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
 License for more details.

 You should have received a copy of the GNU Lesser General Public
 License along with MySQL++; if not, write to the Free Software
 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
 USA
***********************************************************************/

#pragma once


#include <mysql++.h>



namespace wforms {

	using namespace Microsoft::Win32;
	using namespace System;
	using namespace System::ComponentModel;
	using namespace System::Collections;
	using namespace System::Windows::Forms;
	using namespace System::Data;
	using namespace System::Drawing;

	public ref class MainForm : public System::Windows::Forms::Form
	{
	public:
		MainForm()
		{
			InitializeComponent();
			LoadDefaults();
		}

	protected:
		~MainForm()
		{
			if (components) {
				delete components;
			}
		}

	private:
		// Insert a text string into the output list control
		Void AddMessage(String^ msg)
		{
			resultsList_->Items->Add(msg);
		}

		// Handle Close button click by shutting down application
		Void CloseButton_Click(Object^ sender, EventArgs^ e)
		{
			Application::Exit();



		}

		
		// Handle Connect button click.  The body of this function is
		// essentially the same as the simple2 command line example, with
		// some GUI overhead.
		Void ConnectButton_Click(Object^ sender, EventArgs^ e)
		{
			// Clear out the results list, in case this isn't the first time
			// we've come in here.
			resultsList_->Items->Clear();

			// Translate the Unicode text we get from the UI into the UTF-8
			// form that MySQL wants.
			const int kInputBufSize = 100;
			char acServerAddress[kInputBufSize];
			char acUserName[kInputBufSize];
			char acPassword[kInputBufSize];
			ToUTF8(acServerAddress, kInputBufSize, serverAddress_->Text);
			ToUTF8(acUserName, kInputBufSize, userName_->Text);
			ToUTF8(acPassword, kInputBufSize, password_->Text);

			// Connect to the sample database.
			mysqlpp::Connection con(false);
			if (!con.connect("mysql_cpp_data", acServerAddress, acUserName,
					acPassword)) {
				AddMessage("Failed to connect to server:");
				AddMessage(gcnew String(con.error()));
				return;
			}

			// Retrieve a subset of the sample stock table set up by resetdb
			mysqlpp::Query query = con.query();
			query << "select item from stock";
			mysqlpp::StoreQueryResult res = query.store();



			if (res) {
				// Display the result set
				for (size_t i = 0; i < res.num_rows(); ++i) {
					AddMessage(ToUCS2(res[i][0]));
				}


				// Retreive was successful, so save user inputs now
				SaveInputs();
			}
			else {
				// Retreive failed
				AddMessage("Failed to get item list:");
				AddMessage(ToUCS2(query.error()));
			}
		}

		// Load the default input field values, if there are any
		Void LoadDefaults()

		{
			RegistryKey^ settings = OpenSettingsRegistryKey();
			if (settings) {
				userName_->Text = LoadSetting(settings, L"user");
				serverAddress_->Text = LoadSetting(settings, L"server");
			}
			
			if (String::IsNullOrEmpty(userName_->Text)) {
				userName_->Text = Environment::UserName;


			}
			if (String::IsNullOrEmpty(serverAddress_->Text)) {
				serverAddress_->Text = L"localhost";
			}
		}

		// Returns a setting from underneath the given registry key.
		// Assumes that it's a string value under the MySQL++ examples' 
		// settings area.
		String^ LoadSetting(RegistryKey^ key, String^ name)
		{
			return (String^)key->GetValue(name);
		}

		// Returns a reference to the MySQL++ examples' settings area in the
		// registry.
		RegistryKey^ OpenSettingsRegistryKey()
		{
			RegistryKey^ key = Registry::CurrentUser->OpenSubKey(L"Software",
					true);
			return key ? key->CreateSubKey(L"MySQL++ Examples") : nullptr;
		}


		// Saves the input fields' values to the registry, except for the
		// password field.
		Void SaveInputs()
		{
			RegistryKey^ settings = OpenSettingsRegistryKey();
			if (settings) {
				SaveSetting(settings, "user", userName_->Text);
				SaveSetting(settings, "server", serverAddress_->Text);
			}			
		}

		// Saves the given value as a named entry under the given registry
		// key.
		Void SaveSetting(RegistryKey^ key, String^ name, String^ value)



		{
			key->SetValue(name, value);



		}

		// Takes a string in the .NET platform's native Unicode format and
		// copies it to the given C string buffer in UTF-8 encoding.
		Void ToUTF8(char* pcOut, int nOutLen, String^ sIn)
		{
			array<Byte>^ bytes = System::Text::Encoding::UTF8->GetBytes(sIn);
			nOutLen = Math::Min(nOutLen - 1, bytes->Length);
			System::Runtime::InteropServices::Marshal::Copy(bytes, 0, 
				IntPtr(pcOut), nOutLen);
			pcOut[nOutLen] = '\0';

		}

		// Takes the given C string encoded in UTF-8 and converts it to a
		// Unicode string in the .NET platform's native Unicode encoding.
		String^ ToUCS2(const char* utf8)
		{
			return gcnew String(utf8, 0, strlen(utf8), 
					System::Text::Encoding::UTF8);
		}



	private: System::Windows::Forms::TextBox^ serverAddress_;
	private: System::Windows::Forms::TextBox^ password_;
	private: System::Windows::Forms::TextBox^ userName_;
	private: System::Windows::Forms::ListBox^ resultsList_;
	private: System::Windows::Forms::Button^ connectButton_;
	private: System::Windows::Forms::Button^ closeButton_;
	private: System::ComponentModel::Container^ components;


#pragma region Windows Form Designer generated code
		/// <summary>
		/// Required method for Designer support - do not modify
		/// the contents of this method with the code editor.
		/// </summary>
		void InitializeComponent(void)
		{
			System::Windows::Forms::Label^  label1;
			System::Windows::Forms::Label^  label2;
			System::Windows::Forms::Label^  label3;
			System::Windows::Forms::Label^  label4;
			this->serverAddress_ = (gcnew System::Windows::Forms::TextBox());
			this->password_ = (gcnew System::Windows::Forms::TextBox());
			this->userName_ = (gcnew System::Windows::Forms::TextBox());
			this->resultsList_ = (gcnew System::Windows::Forms::ListBox());
			this->connectButton_ = (gcnew System::Windows::Forms::Button());
			this->closeButton_ = (gcnew System::Windows::Forms::Button());
			label1 = (gcnew System::Windows::Forms::Label());
			label2 = (gcnew System::Windows::Forms::Label());
			label3 = (gcnew System::Windows::Forms::Label());
			label4 = (gcnew System::Windows::Forms::Label());
			this->SuspendLayout();
			// 


			// label1
			// 
			label1->AutoSize = true;
			label1->Location = System::Drawing::Point(29, 13);
			label1->Name = L"label1";

			label1->Size = System::Drawing::Size(41, 13);
			label1->TabIndex = 6;
			label1->Text = L"Server:";
			label1->TextAlign = System::Drawing::ContentAlignment::TopRight;
			// 
			// label2
			// 
			label2->AutoSize = true;
			label2->Location = System::Drawing::Point(9, 39);
			label2->Name = L"label2";
			label2->Size = System::Drawing::Size(61, 13);
			label2->TabIndex = 7;
			label2->Text = L"User name:";
			label2->TextAlign = System::Drawing::ContentAlignment::TopRight;

			// 
			// label3
			// 
			label3->AutoSize = true;
			label3->Location = System::Drawing::Point(14, 65);
			label3->Name = L"label3";
			label3->Size = System::Drawing::Size(56, 13);
			label3->TabIndex = 8;
			label3->Text = L"Password:";
			label3->TextAlign = System::Drawing::ContentAlignment::TopRight;
			// 
			// label4
			// 
			label4->AutoSize = true;
			label4->Location = System::Drawing::Point(25, 92);
			label4->Name = L"label4";
			label4->Size = System::Drawing::Size(45, 13);
			label4->TabIndex = 9;
			label4->Text = L"Results:";
			label4->TextAlign = System::Drawing::ContentAlignment::TopRight;
			// 
			// serverAddress_
			// 
			this->serverAddress_->Location = System::Drawing::Point(70, 9);
			this->serverAddress_->Name = L"serverAddress_";

			this->serverAddress_->Size = System::Drawing::Size(139, 20);
			this->serverAddress_->TabIndex = 0;
			// 
			// password_

			// 

			this->password_->Location = System::Drawing::Point(70, 61);
			this->password_->Name = L"password_";
			this->password_->Size = System::Drawing::Size(139, 20);
			this->password_->TabIndex = 2;
			this->password_->UseSystemPasswordChar = true;
			// 



			// userName_
			// 
			this->userName_->Location = System::Drawing::Point(70, 35);
			this->userName_->Name = L"userName_";
			this->userName_->Size = System::Drawing::Size(139, 20);
			this->userName_->TabIndex = 1;
			// 
			// resultsList_
			// 
			this->resultsList_->Enabled = false;
			this->resultsList_->FormattingEnabled = true;
			this->resultsList_->Location = System::Drawing::Point(70, 88);
			this->resultsList_->Name = L"resultsList_";
			this->resultsList_->Size = System::Drawing::Size(228, 95);
			this->resultsList_->TabIndex = 3;
			this->resultsList_->TabStop = false;
			// 
			// connectButton_
			// 
			this->connectButton_->Location = System::Drawing::Point(224, 9);
			this->connectButton_->Name = L"connectButton_";
			this->connectButton_->Size = System::Drawing::Size(75, 23);
			this->connectButton_->TabIndex = 3;
			this->connectButton_->Text = L"Connect!";
			this->connectButton_->UseVisualStyleBackColor = true;
			this->connectButton_->Click += gcnew System::EventHandler(this, &MainForm::ConnectButton_Click);
			// 
			// closeButton_
			// 
			this->closeButton_->DialogResult = System::Windows::Forms::DialogResult::Cancel;
			this->closeButton_->Location = System::Drawing::Point(224, 38);
			this->closeButton_->Name = L"closeButton_";
			this->closeButton_->Size = System::Drawing::Size(75, 23);
			this->closeButton_->TabIndex = 4;
			this->closeButton_->Text = L"Close";
			this->closeButton_->UseVisualStyleBackColor = true;
			this->closeButton_->Click += gcnew System::EventHandler(this, &MainForm::CloseButton_Click);
			// 




			// MainForm
			// 

			this->AcceptButton = this->connectButton_;
			this->AutoScaleDimensions = System::Drawing::SizeF(6, 13);
			this->AutoScaleMode = System::Windows::Forms::AutoScaleMode::Font;
			this->CancelButton = this->closeButton_;
			this->ClientSize = System::Drawing::Size(310, 192);
			this->ControlBox = false;
			this->Controls->Add(label4);
			this->Controls->Add(label3);
			this->Controls->Add(label2);
			this->Controls->Add(label1);
			this->Controls->Add(this->closeButton_);
			this->Controls->Add(this->connectButton_);
			this->Controls->Add(this->resultsList_);
			this->Controls->Add(this->userName_);
			this->Controls->Add(this->password_);
			this->Controls->Add(this->serverAddress_);
			this->FormBorderStyle = System::Windows::Forms::FormBorderStyle::FixedDialog;
			this->MaximizeBox = false;
			this->MinimizeBox = false;
			this->Name = L"MainForm";
			this->ShowIcon = false;
			this->Text = L"MySQL++ Windows Forms Examples";
			this->ResumeLayout(false);
			this->PerformLayout();






		}
#pragma endregion
};
}

|
|
>
>
>

>
|
>
|
|



















|
>



>
>
|

|
<
<
<
<
|
<

<
|
<
<
<
<
<
<
|
<
<
|
<
<
|
<
|
<
<
<
<
<
<
|
<
<
|
<
>
>
>
|
>
|
|
|
|
|
|
|
|
|
|
<
|
<
<
<
<
<
<
<
|
<
<
<
<
<
<
<
|

<
<
<
<
>
>
|
<
|
|
<
<
>
|
<
|
|
<
<
<
<
|
|
|
<
<
>
|
<
|
<
<
<
|
|
<
>
>
|
<
<
<
<
|
<
<
|
<
<
|
|
<
<
<
<
|
|
|
|
<
|
>
|
|
<
<
<
<
<
<
|
|
|
<
<
<
>
>
>
|
<
>
>
>
|

<
<
|
<
<
<
<
<
<
>
|

<
<
<
<
<
<
|
>
>
|
<
|
|
|
|
|
|
|
>
|
|
<
|
|
<
|
<
<
<
<
<
<
<
<
|
<
<
<
<
<
<
<
>
>
|
<
<
<
<
>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
>
|
|
<
|
|
|
|
|
<
<
<
|
<
<
<
<
<
<
<
<
<
|
<
<
<
>
|
<
<
|
>
|
>
|
|
|
|
|
<
>
>
>
|
<
<
|
|
<
|
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
|
|
|
|
|
|
|
|
<
<
>
>
>
>
|
<
>
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
|
<
<
<
<
<
<
<
|
>
|
>
>
>
>
|
<
<

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
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
56
57
58
59
60
61
62
63
64
65

66







67







68
69




70
71
72

73
74


75
76

77
78




79
80
81


82
83

84



85
86

87
88
89




90


91


92
93




94
95
96
97

98
99
100
101






102
103
104



105
106
107
108

109
110
111
112
113


114






115
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
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


191
192
193
194
195

196
197














198







199
200
201
202
203
204
205
206


207
/***********************************************************************
 multiquery.cpp - Example showing how to iterate over result sets upon
	execution of a query that returns more than one result set.  You can
	get multiple result sets when executing multiple separate SQL
	statments in a single query, or when dealing with the results of
	calling a stored procedure.

 Copyright (c) 1998 by Kevin Atkinson, (c) 1999, 2000 and 2001 by
 MySQL AB, (c) 2004, 2005 by Educational Technology Resources, Inc.,
 and (c) 2005 by Arnon Jalon.  Others may also hold copyrights on
 code in this file.  See the CREDITS.txt file in the top directory of
 the distribution for details.

 This file is part of MySQL++.

 MySQL++ is free software; you can redistribute it and/or modify it
 under the terms of the GNU Lesser General Public License as published
 by the Free Software Foundation; either version 2.1 of the License, or
 (at your option) any later version.

 MySQL++ is distributed in the hope that it will be useful, but WITHOUT
 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
 License for more details.

 You should have received a copy of the GNU Lesser General Public
 License along with MySQL++; if not, write to the Free Software
 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
 USA
***********************************************************************/

#include "cmdline.h"
#include "printdata.h"

#include <mysql++.h>

#include <iostream>
#include <iomanip>
#include <vector>

using namespace std;




using namespace mysqlpp;










typedef vector<int> IntVectorType;







static void






print_header(IntVectorType& widths, StoreQueryResult& res)


{

	cout << "  |" << setfill(' ');
	for (size_t i = 0; i < res.field_names()->size(); i++) {
		cout << " " << setw(widths.at(i)) << res.field_name(i) << " |";
	}
	cout << endl;
}


static void
print_row(IntVectorType& widths, Row& row)
{
	cout << "  |" << setfill(' ');
	for (size_t i = 0; i < row.size(); ++i) {
		cout << " " << setw(widths.at(i)) << row[i] << " |";
	}

	cout << endl;







}













static void
print_row_separator(IntVectorType& widths)
{

	cout << "  +" << setfill('-');
	for (size_t i = 0; i < widths.size(); i++) {


		cout << "-" << setw(widths.at(i)) << '-' << "-+";
	}

	cout << endl;
}






static void


print_result(StoreQueryResult& res, int index)
{

	// Show how many rows are in result, if any



	StoreQueryResult::size_type num_results = res.size();
	if (res && (num_results > 0)) {

		cout << "Result set " << index << " has " << num_results <<
				" row" << (num_results == 1 ? "" : "s") << ':' << endl;
	}




	else {


		cout << "Result set " << index << " is empty." << endl;


		return;
	}





	// Figure out the widths of the result set's columns
	IntVectorType widths;
	int size = res.num_fields();

	for (int i = 0; i < size; i++) {
		widths.push_back(max(
				res.field(i).max_length(),
				res.field_name(i).size()));






	}

	// Print result set header



	print_row_separator(widths);
	print_header(widths, res);
	print_row_separator(widths);


	// Display the result set contents
	for (StoreQueryResult::size_type i = 0; i < num_results; ++i) {
		print_row(widths, res[i]);
	}



	// Print result set footer






	print_row_separator(widths);
}








static void
print_multiple_results(Query& query)
{

	// Execute query and print all result sets
	StoreQueryResult res = query.store();
	print_result(res, 0);
	for (int i = 1; query.more_results(); ++i) {
		res = query.store_next();
		print_result(res, i);
	}
}



int
main(int argc, char *argv[])

{








	// Get connection parameters from command line







	const char* db = 0, *server = 0, *user = 0, *pass = "";
	if (!parse_command_line(argc, argv, &db, &server, &user, &pass)) {
		return 1;




	}

	try {
		// Enable multi-queries.  Notice that you almost always set
		// MySQL++ connection options before establishing the server
		// connection, and options are always set using this one
		// interface.  If you're familiar with the underlying C API,
		// you know that there is poor consistency on these matters;
		// MySQL++ abstracts these differences away.
		Connection con;
		con.set_option(new MultiStatementsOption(true));

		// Connect to the database
		if (!con.connect(db, server, user, pass)) {
			return 1;
		}

		// Set up query with multiple queries.

		Query query = con.query();
		query << "DROP TABLE IF EXISTS test_table; " <<
				"CREATE TABLE test_table(id INT); " <<
				"INSERT INTO test_table VALUES(10); " <<
				"UPDATE test_table SET id=20 WHERE id=10; " <<



				"SELECT * FROM test_table; " <<









				"DROP TABLE test_table";



		cout << "Multi-query: " << endl << query << endl;



		// Execute statement and display all result sets.
		print_multiple_results(query);

#if MYSQL_VERSION_ID >= 50000
		// If it's MySQL v5.0 or higher, also test stored procedures, which
		// return their results the same way multi-queries do.
		query << "DROP PROCEDURE IF EXISTS get_stock; " <<
				"CREATE PROCEDURE get_stock" <<
				"( i_item varchar(20) ) " <<

				"BEGIN " <<
				"SET i_item = concat('%', i_item, '%'); " <<
				"SELECT * FROM stock WHERE lower(item) like lower(i_item); " <<
				"END;";


		cout << "Stored procedure query: " << endl << query << endl;


		// Create the stored procedure.
		print_multiple_results(query);





















		// Call the stored procedure and display its results.
		query << "CALL get_stock('relish')";
		cout << "Query: " << query << endl;
		print_multiple_results(query);
#endif

		return 0;


	}
	catch (const BadOption& err) {
		cerr << err.what() << endl;
		cerr << "This example requires MySQL 4.1.1 or later." << endl;
		return 1;

	}
	catch (const ConnectionFailed& err) {














		cerr << "Failed to connect to database server: " <<







				err.what() << endl;
		return 1;
	}
	catch (const Exception& er) {
		// Catch-all for any other MySQL++ exceptions
		cerr << "Error: " << er.what() << endl;
		return 1;
	}


}

Changes to examples/vstudio/wforms/MainForm.resX.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
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



56
57
58
59

60
61
62
63
64
65
66



67
68
69
70
71
72
73
74
75
76
77
78
79

80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109


110
111
112
113

114
115
116
117
118

119
120
121
122
123
124
125
126
127
128
129
130
131
132
<?xml version="1.0" encoding="utf-8"?>
<root>
  <!-- 
    Microsoft ResX Schema 
    
    Version 2.0
    
    The primary goals of this format is to allow a simple XML format 
    that is mostly human readable. The generation and parsing of the 
    various data types are done through the TypeConverter classes 
    associated with the data types.
    
    Example:
    
    ... ado.net/XML headers & schema ...
    <resheader name="resmimetype">text/microsoft-resx</resheader>
    <resheader name="version">2.0</resheader>
    <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
    <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
    <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
    <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
    <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
        <value>[base64 mime encoded serialized .NET Framework object]</value>
    </data>
    <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
        <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
        <comment>This is a comment</comment>
    </data>
                
    There are any number of "resheader" rows that contain simple 
    name/value pairs.

    
    Each data row contains a name, and value. The row also contains a 

    type or mimetype. Type corresponds to a .NET class that support 
    text/value conversion through the TypeConverter architecture. 
    Classes that don't support this are serialized and stored with the 
    mimetype set.
    
    The mimetype is used for serialized objects, and tells the 
    ResXResourceReader how to depersist the object. This is currently not 
    extensible. For a given mimetype the value must be set accordingly:
    
    Note - application/x-microsoft.net.object.binary.base64 is the format 
    that the ResXResourceWriter will generate, however the reader can 

    read any of the formats listed below.
    
    mimetype: application/x-microsoft.net.object.binary.base64
    value   : The object must be serialized with 
            : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
            : and then encoded with base64 encoding.
    
    mimetype: application/x-microsoft.net.object.soap.base64
    value   : The object must be serialized with 
            : System.Runtime.Serialization.Formatters.Soap.SoapFormatter
            : and then encoded with base64 encoding.




    mimetype: application/x-microsoft.net.object.bytearray.base64
    value   : The object must be serialized into a byte array 
            : using a System.ComponentModel.TypeConverter

            : and then encoded with base64 encoding.
    -->
  <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
    <xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
    <xsd:element name="root" msdata:IsDataSet="true">
      <xsd:complexType>
        <xsd:choice maxOccurs="unbounded">



          <xsd:element name="metadata">
            <xsd:complexType>
              <xsd:sequence>
                <xsd:element name="value" type="xsd:string" minOccurs="0" />
              </xsd:sequence>
              <xsd:attribute name="name" use="required" type="xsd:string" />
              <xsd:attribute name="type" type="xsd:string" />
              <xsd:attribute name="mimetype" type="xsd:string" />
              <xsd:attribute ref="xml:space" />
            </xsd:complexType>
          </xsd:element>
          <xsd:element name="assembly">
            <xsd:complexType>

              <xsd:attribute name="alias" type="xsd:string" />
              <xsd:attribute name="name" type="xsd:string" />
            </xsd:complexType>
          </xsd:element>
          <xsd:element name="data">
            <xsd:complexType>
              <xsd:sequence>
                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
                <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
              </xsd:sequence>
              <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
              <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
              <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
              <xsd:attribute ref="xml:space" />
            </xsd:complexType>
          </xsd:element>
          <xsd:element name="resheader">
            <xsd:complexType>
              <xsd:sequence>
                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
              </xsd:sequence>
              <xsd:attribute name="name" type="xsd:string" use="required" />
            </xsd:complexType>
          </xsd:element>
        </xsd:choice>
      </xsd:complexType>
    </xsd:element>
  </xsd:schema>
  <resheader name="resmimetype">
    <value>text/microsoft-resx</value>


  </resheader>
  <resheader name="version">
    <value>2.0</value>
  </resheader>

  <resheader name="reader">
    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
  </resheader>
  <resheader name="writer">
    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>

  </resheader>
  <metadata name="label1.GenerateMember" type="System.Boolean, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
    <value>False</value>
  </metadata>
  <metadata name="label2.GenerateMember" type="System.Boolean, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
    <value>False</value>
  </metadata>
  <metadata name="label3.GenerateMember" type="System.Boolean, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
    <value>False</value>
  </metadata>
  <metadata name="label4.GenerateMember" type="System.Boolean, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
    <value>False</value>
  </metadata>
</root>
|
|
<
<
|
<
|
<
<
<
<
|
<
|
<
<
<
|
<
<
<
<
<
<
<
<
<
<
|
<
<
>
|
<
>
<
<
<
<
|
<
<
<
|
<
|
>
|
|
<
<
<
<
|
<
<
<
<
>
>
>

<
<
<
>
|
<
<
<
<
<
<
>
>
>
|
|
|
|
|
<
|
|
|
|
<
<
<
>
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
|
<
|
<
<
<
<
<
<
<
>
>
|
|
<
|
>
|
<
<
|
|
>
|
<
<
<
<
<
<
<
<
<
<
<
<
<
1
2


3

4




5

6



7










8


9
10

11




12



13

14
15
16
17




18




19
20
21
22



23
24






25
26
27
28
29
30
31
32

33
34
35
36



37
38



















39

40







41
42
43
44

45
46
47


48
49
50
51













/// \file stream2string.h
/// \brief Declares an adapter that converts something that can be


/// inserted into a C++ stream into a std::string type.






/***********************************************************************

 Copyright (c) 1998 by Kevin Atkinson, (c) 1999-2001 by MySQL AB, and



 (c) 2004-2007 by Educational Technology Resources, Inc.  Others may










 also hold copyrights on code in this file.  See the CREDITS file in


 the top directory of the distribution for details.


 This file is part of MySQL++.








 MySQL++ is free software; you can redistribute it and/or modify it

 under the terms of the GNU Lesser General Public License as published
 by the Free Software Foundation; either version 2.1 of the License, or
 (at your option) any later version.





 MySQL++ is distributed in the hope that it will be useful, but WITHOUT




 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
 License for more details.




 You should have received a copy of the GNU Lesser General Public
 License along with MySQL++; if not, write to the Free Software






 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
 USA
***********************************************************************/

#if !defined(MYSQLPP_STREAM2STRING_H)
#define MYSQLPP_STREAM2STRING_H

#include <sstream>

#include <string>

namespace mysqlpp {




/// \brief Converts anything you can insert into a C++ stream to a
/// \c std::string via \c std::ostringstream.





















template <class T>







std::string stream2string(const T& object)
{
	std::ostringstream str;
	str << object;

	return str.str();
}



} // end namespace mysqlpp

#endif // !defined(MYSQLPP_STREAM2STRING_H)














Changes to examples/vstudio/wforms/resource.h.



1





2

3










































































































































































































































































//{{NO_DEPENDENCIES}}





// Microsoft Visual C++ generated include file.

// Used by app.rc








































































































































































































































































>
>
|
>
>
>
>
>
|
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
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
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
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
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
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
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
269
270
271
272
273
274
275
/// \file tiny_int.h
/// \brief Declares class for holding a SQL TINYINT

/***********************************************************************
 Copyright (c) 1998 by Kevin Atkinson, (c) 1999-2001 by MySQL AB, and
 (c) 2004-2007 by Educational Technology Resources, Inc.  Others may
 also hold copyrights on code in this file.  See the CREDITS file in
 the top directory of the distribution for details.

 This file is part of MySQL++.

 MySQL++ is free software; you can redistribute it and/or modify it
 under the terms of the GNU Lesser General Public License as published
 by the Free Software Foundation; either version 2.1 of the License, or
 (at your option) any later version.

 MySQL++ is distributed in the hope that it will be useful, but WITHOUT
 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
 License for more details.

 You should have received a copy of the GNU Lesser General Public
 License along with MySQL++; if not, write to the Free Software
 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
 USA
***********************************************************************/

#if !defined(MYSQLPP_TINY_INT_H)
#define MYSQLPP_TINY_INT_H

#include "common.h"

#include <ostream>

namespace mysqlpp {

/// \brief Class for holding an SQL \c TINYINT value
///
/// This is required because the closest C++ type, \c char, doesn't
/// have all the right semantics.  For one, inserting a \c char into a
/// stream won't give you a number.  For another, if you don't specify
/// signedness explicitly, C++ doesn't give a default, so it's signed
/// on some platforms, unsigned on others.
///
/// The template parameter is intended to allow instantiating it as
/// tiny_int<unsigned char> to hold \c TINYINT \c UNSIGNED values.
/// There's nothing stopping you from using any other integer type if
/// you want to be perverse, but please don't do that.
///
/// Several of the functions below accept an \c int argument, but
/// internally we store the data as a \c char by default. Beware of
/// integer overflows!

template <typename VT = signed char>
class tiny_int
{
public:
	//// Type aliases
	typedef tiny_int<VT> this_type;	///< alias for this object's type
	typedef VT value_type;			///< alias for type of internal value

	/// \brief Default constructor
	///
	/// Value is uninitialized
	tiny_int() { }
	
	/// \brief Create object from any integral type that can be
	/// converted to a \c short \c int.
	tiny_int(value_type v) :
	value_(value_type(v))
	{
	}
	
	/// \brief Return truthiness of value
	operator bool() const
	{
		return value_;
	}

	/// \brief Return value as an \c int.
	operator int() const
	{
		return static_cast<int>(value_);
	}

	/// \brief Return raw data value with no size change
	operator value_type() const
	{
		return value_;
	}

	/// \brief Assign a new value to the object.
	this_type& operator =(int v)
	{
		value_ = static_cast<value_type>(v);
		return *this;
	}

	/// \brief Add another value to this object
	this_type& operator +=(int v)
	{
		value_ += static_cast<value_type>(v);
		return *this;
	}

	/// \brief Subtract another value to this object
	this_type& operator -=(int v)
	{
		value_ -= static_cast<value_type>(v);
		return *this;
	}

	/// \brief Multiply this value by another object
	this_type& operator *=(int v)
	{
		value_ *= static_cast<value_type>(v);
		return *this;
	}

	/// \brief Divide this value by another object
	this_type& operator /=(int v)
	{
		value_ /= static_cast<value_type>(v);
		return *this;
	}

	/// \brief Divide this value by another object and store the
	/// remainder
	this_type& operator %=(int v)
	{
		value_ %= static_cast<value_type>(v);
		return *this;
	}

	/// \brief Bitwise AND this value by another value
	this_type& operator &=(int v)
	{
		value_ &= static_cast<value_type>(v);
		return *this;
	}

	/// \brief Bitwise OR this value by another value
	this_type& operator |=(int v)
	{
		value_ |= static_cast<value_type>(v);
		return *this;
	}

	/// \brief Bitwise XOR this value by another value
	this_type& operator ^=(int v)
	{
		value_ ^= static_cast<value_type>(v);
		return *this;
	}

	/// \brief Shift this value left by \c v positions
	this_type& operator <<=(int v)
	{
		value_ <<= static_cast<value_type>(v);
		return *this;
	}

	/// \brief Shift this value right by \c v positions
	this_type& operator >>=(int v)
	{
		value_ >>= static_cast<value_type>(v);
		return *this;
	}

	/// \brief Add one to this value and return that value
	this_type& operator ++()
	{
		++value_;
		return *this;
	}

	/// \brief Subtract one from this value and return that value
	this_type& operator --()
	{
		--value_;
		return *this;
	}

	/// \brief Add one to this value and return the previous value
	this_type operator ++(int)
	{
		this_type tmp = value_;
		++value_;
		return tmp;
	}

	/// \brief Subtract one from this value and return the previous
	/// value
	this_type operator --(int)
	{
		this_type tmp = value_;
		--value_;
		return tmp;
	}

	/// \brief Return this value minus \c i
	this_type operator -(const this_type& i) const
	{
		return value_ - i.value_;
	}
	
	/// \brief Return this value plus \c i
	this_type operator +(const this_type& i) const
	{
		return value_ + i.value_;
	}
	
	/// \brief Return this value multiplied by \c i
	this_type operator *(const this_type& i) const
	{
		return value_ * i.value_;
	}
	
	/// \brief Return this value divided by \c i
	this_type operator /(const this_type& i) const
	{
		return value_ / i.value_;
	}
	
	/// \brief Return the modulus of this value divided by \c i
	this_type operator %(const this_type& i) const
	{
		return value_ % i.value_;
	}
	
	/// \brief Return this value bitwise OR'd by \c i
	this_type operator |(const this_type& i) const
	{
		return value_ | i.value_;
	}
	
	/// \brief Return this value bitwise AND'd by \c i
	this_type operator &(const this_type& i) const
	{
		return value_ & i.value_;
	}
	
	/// \brief Return this value bitwise XOR'd by \c i
	this_type operator ^(const this_type& i) const
	{
		return value_ ^ i.value_;
	}
	
	/// \brief Return this value bitwise shifted left by \c i
	this_type operator <<(const this_type& i) const
	{
		return value_ << i.value_;
	}
	
	/// \brief Return this value bitwise shifted right by \c i
	this_type operator >>(const this_type& i) const
	{
		return value_ >> i.value_;
	}

private:
	value_type value_;
};

/// \brief Insert a \c tiny_int into a C++ stream
template <typename VT>
std::ostream& operator <<(std::ostream& os, tiny_int<VT> i)
{
	os << static_cast<int>(i);
	return os;
}

} // end namespace mysqlpp

#endif

Changes to examples/vstudio/wforms/wforms.cpp.






1





2

























3


4
5









































































































































6

7






8





9



10





11




12






















































13



14


15

























16
17





















































// wforms.cpp : main project file.































#include "MainForm.h"



using namespace wforms;











































































































































[STAThreadAttribute]






int main(array<System::String ^> ^args)





{



	// Enabling Windows XP visual effects before any controls are created





	Application::EnableVisualStyles();




	Application::SetCompatibleTextRenderingDefault(false); 


























































	// Create the main window and run it


	Application::Run(gcnew MainForm());

























	return 0;
}
















































>
>
>
>
>
|
>
>
>
>
>

>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
>

|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
|
>
>
>
>
>
>
|
>
>
>
>
>
|
>
>
>
|
>
>
>
>
>
|
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

>
>
>
|
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
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
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
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
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
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
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
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
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
336
337
338
339
340
341
342
343
344
345
346
347
/// \file type_info.h
/// \brief Declares classes that provide an interface between the SQL
/// and C++ type systems.
///
/// These classes are mostly used internal to the library.

/***********************************************************************
 Copyright (c) 1998 by Kevin Atkinson, (c) 1999-2001 by MySQL AB, and
 (c) 2004-2008 by Educational Technology Resources, Inc.  Others may
 also hold copyrights on code in this file.  See the CREDITS file in
 the top directory of the distribution for details.

 This file is part of MySQL++.

 MySQL++ is free software; you can redistribute it and/or modify it
 under the terms of the GNU Lesser General Public License as published
 by the Free Software Foundation; either version 2.1 of the License, or
 (at your option) any later version.

 MySQL++ is distributed in the hope that it will be useful, but WITHOUT
 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
 License for more details.

 You should have received a copy of the GNU Lesser General Public
 License along with MySQL++; if not, write to the Free Software
 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
 USA
***********************************************************************/

#if !defined(MYSQLPP_TYPE_INFO_H)
#define MYSQLPP_TYPE_INFO_H

#include "common.h"

#include "exceptions.h"

#include <map>
#include <sstream>
#include <typeinfo>

namespace mysqlpp {

#if !defined(DOXYGEN_IGNORE)
// Doxygen will not generate documentation for this section.

class MYSQLPP_EXPORT mysql_type_info;
class MYSQLPP_EXPORT mysql_ti_sql_type_info_lookup;

class MYSQLPP_EXPORT mysql_ti_sql_type_info
{
private:
	// For use with flags_ bitset
	enum {
		tf_default = 1,
		tf_null = 2,
		tf_unsigned = 4
	};

	friend class mysql_type_info;
	friend class mysql_ti_sql_type_info_lookup;

	mysql_ti_sql_type_info& operator=(
			const mysql_ti_sql_type_info& b);
	
	// Not initting _base_type and _default because only mysql_type_info
	// can create them.  There *must* be only one copy of each.
	mysql_ti_sql_type_info() :
	sql_name_(0),
	c_type_(0),
	base_type_(MYSQL_TYPE_NULL),
	flags_(0)
	{
	}
	
	mysql_ti_sql_type_info(const char* s,
			const std::type_info& t, const enum_field_types bt,
			const unsigned int flags = 0) :
	sql_name_(s),
	c_type_(&t),
	base_type_(bt),
	flags_(flags)
	{
	}

	bool is_default() const { return flags_ & tf_default; }
	bool is_null() const { return flags_ & tf_null; }
	bool is_unsigned() const { return flags_ & tf_unsigned; }

	const char* sql_name_;
	const std::type_info* c_type_;
	const enum_field_types base_type_;
	const unsigned int flags_;
};


struct type_info_cmp
{
	bool operator() (const std::type_info* lhs,
			const std::type_info* rhs) const
	{
		return lhs->before(*rhs) != 0;
	}
};

class MYSQLPP_EXPORT mysql_ti_sql_type_info_lookup
{
private:
	friend class mysql_type_info;

	typedef mysql_ti_sql_type_info sql_type_info;
	typedef std::map<const std::type_info*, unsigned char, type_info_cmp>
			map_type;

	mysql_ti_sql_type_info_lookup(const sql_type_info types[],
			const int size);

	const unsigned char& operator [](
			const std::type_info& ti) const
	{
		map_type::const_iterator it = map_.find(&ti);
		if (it != map_.end()) {
			return it->second;
		}
		else {
			std::ostringstream outs;
			outs << "Failed to find MySQL C API type ID for " << ti.name();
			throw TypeLookupFailed(outs.str());
		}
	}

	map_type map_;
};

#endif // !defined(DOXYGEN_IGNORE)


/// \brief SQL field type information
///
/// \internal Used within MySQL++ for mapping SQL types to C++ types
/// and vice versa.
class MYSQLPP_EXPORT mysql_type_info
{
public:
	/// \brief Default constructor
	///
	/// This only exists because FieldTypes keeps a vector of these
	/// objects.  You are expected to copy real values into it before
	/// using it via the copy ctor or one of the assignment operators.
	/// If you don't, we have arranged a pretty spectacular crash for
	/// your program.  So there.
	mysql_type_info() :
	num_(static_cast<unsigned char>(-1))
	{
	}

	/// \brief Create object from MySQL C API type info
	///
	/// \param t the underlying C API type ID for this type
	/// \param _unsigned if true, this is the unsigned version of the type
	/// \param _null if true, this type can hold a SQL null
	mysql_type_info(enum_field_types t, bool _unsigned = false,
			bool _null = false) :
	num_(type(t, _unsigned, _null))
	{
	}

	/// \brief Create object as a copy of another
	mysql_type_info(const mysql_type_info& t) :
	num_(t.num_)
	{
	}

	/// \brief Create object from a C++ type_info object
	///
	/// This tries to map a C++ type to the closest MySQL data type.
	/// It is necessarily somewhat approximate.
	mysql_type_info(const std::type_info& t) :
	num_(lookups[t])
	{
	}

	/// \brief Assign another mysql_type_info object to this object
	mysql_type_info& operator =(const mysql_type_info& t)
	{
		num_ = t.num_;
		return *this;
	}

	/// \brief Assign a C++ type_info object to this object
	///
	/// This tries to map a C++ type to the closest MySQL data type.
	/// It is necessarily somewhat approximate.
	mysql_type_info& operator =(const std::type_info& t)
	{
		num_ = lookups[t];
		return *this;
	}

	/// \brief Returns an implementation-defined name of the C++ type.
	///
	/// Returns the name that would be returned by typeid().name() for
	/// the C++ type associated with the SQL type.
	const char* name() const { return deref().c_type_->name(); }

	/// \brief Returns the name of the SQL type.
	///
	/// Returns the SQL name for the type.
	const char* sql_name() const { return deref().sql_name_; }

	/// \brief Returns the type_info for the C++ type associated with
	/// the SQL type.
	///
	/// Returns the C++ type_info record corresponding to the SQL type.
	const std::type_info& c_type() const { return *deref().c_type_; }

	/// \brief Returns the type_info for the C++ type inside of the
	/// mysqlpp::Null type.
	///
	/// Returns the type_info for the C++ type inside the mysqlpp::Null
	/// type.  If the type is not Null then this is the same as c_type().
	const mysql_type_info base_type() const
	{
		return mysql_type_info(deref().base_type_);
	}

	/// \brief Returns the ID of the SQL type.
	///
	/// Returns the ID number MySQL uses for this type.  Note: Do not
	/// depend on the value of this ID as it may change between MySQL
	/// versions.
	int id() const
	{
		return num_;
	}
	
	/// \brief Returns true if the SQL type is of a type that needs to
	/// be quoted.
	///
	/// \return true if the type needs to be quoted for syntactically
	/// correct SQL.
	bool quote_q() const;

	/// \brief Returns true if the SQL type is of a type that needs to
	/// be escaped.
	///
	/// \return true if the type needs to be escaped for syntactically
	/// correct SQL.
	bool escape_q() const;

	/// \brief Provides a way to compare two types for sorting.
	///
	/// Returns true if the SQL ID of this type is lower than that of
	/// another.  Used by mysqlpp::type_info_cmp when comparing types.
	bool before(mysql_type_info& b)
	{
		return num_ < b.num_;
	}

	/// \brief The internal constant we use for our string type.
	///
	/// We expose this because other parts of MySQL++ need to know
	/// what the string constant is at the moment.
	static const enum_field_types string_type = MYSQL_TYPE_STRING;

private:
	typedef mysql_ti_sql_type_info sql_type_info;
	typedef mysql_ti_sql_type_info_lookup sql_type_info_lookup;

	static const sql_type_info types[];
	static const int num_types;

	static const sql_type_info_lookup lookups;

	/// \brief Return an index into mysql_type_info::types array given
	/// MySQL type information.
	///
	/// This function is used in mapping from MySQL type information
	/// (a type enum, and flags indicating whether it is unsigned and
	/// whether it can be 'null') to the closest C++ types available
	/// within MySQL++.  Notice that nulls have to be handled specially:
	/// the SQL null concept doesn't map directly onto the C++ type
	/// system.  See null.h for details.
	///
	/// \param t Underlying C API type constant
	/// \param _unsigned if true, indicates the unsigned variant of a
	/// MySQL type
	/// \param _null if true, indicates the variant of the MySQL type
	/// that can also hold an SQL 'null' instead of regular data.
	///
	/// While MySQL++ is tied to MySQL, \c t is just an abstraction
	/// of enum_field_types from mysql_com.h.
	static unsigned char type(enum_field_types t,
			bool _unsigned, bool _null = false);

	const sql_type_info& deref() const
	{
		return types[num_];
	}

	unsigned char num_;
};

/// \brief Returns true if two mysql_type_info objects are equal.
inline bool operator ==(const mysql_type_info& a, const mysql_type_info& b)
{
	return a.id() == b.id();
}

/// \brief Returns true if two mysql_type_info objects are not equal.
inline bool operator !=(const mysql_type_info& a, const mysql_type_info& b)
{
	return a.id() != b.id();
}

/// \brief Returns true if a given mysql_type_info object is equal
/// to a given C++ type_info object.
inline bool operator ==(const std::type_info& a, const mysql_type_info& b)
{
	return a == b.c_type();
}

/// \brief Returns true if a given mysql_type_info object is not equal
/// to a given C++ type_info object.
inline bool operator !=(const std::type_info& a, const mysql_type_info& b)
{
	return a != b.c_type();
}

/// \brief Returns true if a given mysql_type_info object is equal
/// to a given C++ type_info object.
inline bool operator ==(const mysql_type_info& a, const std::type_info& b)
{
	return a.c_type() == b;
}

/// \brief Returns true if a given mysql_type_info object is not equal
/// to a given C++ type_info object.
inline bool operator !=(const mysql_type_info& a, const std::type_info& b)
{
	return a.c_type() != b;
}

}								// end namespace mysqlpp

#endif // !defined(MYSQLPP_TYPE_INFO_H)

Changes to exrun.


1


























2





































3
4

5

6









7































8






9



10








11



12








13

14






















































































































































































































































15
16
17
18

19


20


21







22


23
24
25

26



27




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

56

57
58

59

60

61

62
63
64





65

66

#!/bin/sh


























if [ -z "$1" ]





































then
	echo "usage: $0 [TOOL] <example> [args...]"

	echo

	echo "   Runs the given example, using the library in the current directory"









	echo "   instead of using the system library search mechanism.  Accepts an "































	echo "   arbitrary number of arguments."






	echo



	echo "   TOOL can be 'valgrind', 'gdb', or 'ldd', which causes exrun to"








	echo "   run the example program under the given tool."



	echo








	exit 1

fi























































































































































































































































TOOL=
PROG=$1
if [ "$PROG" = 'valgrind' ]

then


	TOOL='valgrind'


	shift







	PROG=$1


elif [ "$PROG" = 'gdb' ]
then
	TOOL='gdb --args'

	shift



	PROG=$1




elif [ "$PROG" = 'ldd' ]

then
	TOOL='ldd'
	shift



	PROG=$1


fi



























































































































































































































































































































































shift
if [ -e "$PROG" ]
then

	if [ `uname -s` = 'Darwin' ]




	then




		DYLD_LIBRARY_PATH=. $TOOL ./$PROG $*




	elif [ `uname -o` = 'Cygwin' ]




	then




		# Cygwin build case; see below for bash-as-DOS-shell case




		PATH=. $TOOL ./$PROG $*




	elif [ -e /usr/bin/ldd ]




	then




		if [ `uname -s` = 'SunOS' ]




		then






			LD_LIBRARY_PATH=.:/usr/mysql/lib/mysql $TOOL ./$PROG $*








		else

			LD_LIBRARY_PATH=. $TOOL ./$PROG $*


		fi



	else



		echo "ERROR: I don't grok this system's dynamic linkage system."



	fi

elif [ `uname -o` = 'Cygwin' ]

then
	# VC++ build, but using Cygwin's bash as shell to run programs

	cmd.exe /c exrun.bat $PROG $*

else

	echo "usage: $0 [TOOL] <example> [args...]"

	echo
	echo "   Run $0 without arguments for more detailed usage info."
	echo





	exit 1

fi
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
|
>
|
>
|
>
>
>
>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
>
>
>
>
>
|
>
>
>
|
>
>
>
>
>
>
>
>
|
>
>
>
|
>
>
>
>
>
>
>
>
|
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

<
<
<
>
|
>
>
|
>
>
|
>
>
>
>
>
>
>
|
>
>
|
|
|
>
|
>
>
>
|
>
>
>
>
|
>
|
<
|
>
>
>
|
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

|
|
|
>
|
>
>
>
>
|
>
>
>
>
|
>
>
>
>
|
>
>
>
>
|
>
>
>
>
|
>
>
>
>
|
>
>
>
>
|
>
>
>
>
|
>
>
>
>
|
>
>
>
>
|
>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
|
>
|
>
>
|
>
>
>
|
>
>
>
|
>
>
>
|
>
|
>
|
|
>
|
>
|
>
|
>
|
|
|
>
>
>
>
>
|
>
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
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
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
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
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
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
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
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
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
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
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396



397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430

431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
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
#!/usr/bin/perl -w

########################################################################
# ssqls.pl - Generates ssqls.h, as it defines many near-duplicate
#	functions and classes, varying only in trivial ways.
#
# Copyright (c) 1998 by Kevin Atkinson, (c) 1999-2001 by MySQL AB, and
# (c) 2004-2008 by Educational Technology Resources, Inc.  Others may
# also hold copyrights on code in this file.  See the CREDITS file in
# the top directory of the distribution for details.
#
# This file is part of MySQL++.
#
# MySQL++ is free software; you can redistribute it and/or modify it
# under the terms of the GNU Lesser General Public License as published
# by the Free Software Foundation; either version 2.1 of the License, or
# (at your option) any later version.
#
# MySQL++ is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
# License for more details.
#
# You should have received a copy of the GNU Lesser General Public
# License along with MySQL++; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
# USA
########################################################################


# This is the limit on the number of SSQLS data members.  Higher values
# will make ssqls.h exponentially larger.  This will increase compile
# times and may even expose limits in your compiler.  Increase it only
# if and as far as you must.
my $max_data_members = 25;

# To make comparisons between floating point values, we subtract them,
# take the absolute value, and test to see if that delta is under this
# value.  If it is, we call the two values "equal".  Change this as fits
# your need for precision.  Note that we express it as a string because
# we want the value copied literally into ssqls.h, not "preprocessed" 
# by Perl as a floating-point value.
my $fp_min_delta = "0.00001";


# No user-serviceable parts below.

use strict;

open (OUT, ">ssqls.h");

print OUT << "---";

// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
// This file is generated by the Perl script ssqls.pl.  Do not modify
// it directly.  Change the script instead.
// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

#if !defined(MYSQLPP_SSQLS_H)
#define MYSQLPP_SSQLS_H

#include "noexceptions.h"
#include "sql_types.h"

#if !defined(MYSQLPP_SSQLS_COMPATIBLE)
#	error Your compiler is not compatible with the SSQLS feature!
#endif

#include <string>

#include <math.h>

// Smallest difference between two floating point numbers recognized
// in making comparisons.  If the absolute delta is under this
// threshold, the two values are considered equal.  You can either
// override this permanently by changing ssqls.pl, or you can do it
// on a case-by-case basis at compile time by defining this to another
// value before #including this header.
#if !defined(MYSQLPP_FP_MIN_DELTA)
#	define MYSQLPP_FP_MIN_DELTA $fp_min_delta
#endif

namespace mysqlpp {

enum sql_dummy_type { sql_dummy };

#ifdef MYSQLPP_SSQLS_NO_STATICS
#	define MYSQLPP_SSQLS_CONDITIONAL_STATICS(...)
#else
#	define MYSQLPP_SSQLS_CONDITIONAL_STATICS(...) __VA_ARGS__
#endif

---

my @types = ("Date", "DateTime", "Time", "String", "std::string");
foreach my $type (@types) {
	print OUT << "---";

inline int sql_cmp(const $type& a, const $type& b)
{
	return a.compare(b);
}
---
}

@types = (
		"signed char", "unsigned char",
		"sql_tinyint", "sql_tinyint_unsigned",
		"signed int", "unsigned",
		"signed short", "unsigned short",
		"signed long", "unsigned long");
foreach my $type (@types) {
	print OUT << "---";

inline int sql_cmp($type a, $type b)
{
	return a - b;
}
---
}

@types = ("longlong", "ulonglong");
foreach my $type (@types) {
	print OUT << "---";

inline int sql_cmp($type a, $type b) 
{
	if (a == b) return 0;
	if (a <  b) return -1;
	return 1;
}
---
}	

@types = ("double", "float");
foreach my $type (@types) {
	print OUT << "---";

inline int sql_cmp($type a, $type b) 
{
	if (fabs(a - b) < MYSQLPP_FP_MIN_DELTA) return 0;
	if (a <  b) return -1;
	return 1;
}
---
}	

print OUT << "---";

template <typename T>
inline int sql_cmp(const mysqlpp::Null<T>& a, const mysqlpp::Null<T>& b) 
{
	if (a == b) return 0;
	if (a <  b) return -1;
	return 1;
}


// ---------------------------------------------------
//                Begin Mandatory Compare 
// ---------------------------------------------------

#define sql_compare_define(NAME) \\
	bool operator == (const NAME &other) const \\
		{return sql_compare_##NAME<mysqlpp::sql_dummy>(*this,other) == 0;} \\
	bool operator != (const NAME &other) const \\
		{return sql_compare_##NAME<mysqlpp::sql_dummy>(*this,other) != 0;} \\
	bool operator > (const NAME &other) const \\
		{return sql_compare_##NAME<mysqlpp::sql_dummy>(*this,other) >  0;} \\
	bool operator < (const NAME &other) const \\
		{return sql_compare_##NAME<mysqlpp::sql_dummy>(*this,other) <  0;} \\
	bool operator >= (const NAME &other) const \\
		{return sql_compare_##NAME<mysqlpp::sql_dummy>(*this,other) >= 0;} \\
	bool operator <= (const NAME &other) const \\
		{return sql_compare_##NAME<mysqlpp::sql_dummy>(*this,other) <= 0;} \\
	int cmp (const NAME &other) const \\
		{return sql_compare_##NAME<mysqlpp::sql_dummy>(*this,other);} \\
	int compare (const NAME &other) const \\
		{return sql_compare_##NAME<mysqlpp::sql_dummy>(*this,other);}
---

my ($parm0, $parm1);

foreach my $j (1..$max_data_members) {
	$parm0 .= "T$j, C$j";
	$parm0 .= ", " unless $j == $max_data_members;
	$parm1 .= "C$j";
	$parm1 .= ", " unless $j == $max_data_members;
}

print OUT << "---";

#define sql_compare_define_0(NAME, $parm0)

#define sql_construct_define_0(NAME, $parm0)

#define sql_COMPARE__0(NAME, $parm1)

#define sql_compare_type_def_0(NAME, WHAT, NUM) \\
	sql_compare_type_def_##NUM(NAME, WHAT, NUM)

#define sql_compare_type_defe_0(NAME, WHAT, NUM) \\
	sql_compare_type_defe_##NUM(NAME, WHAT, NUM)

// ---------------------------------------------------
//                 End Mandatory Compare 
// ---------------------------------------------------
---


foreach my $i (1..$max_data_members) {
	my ($compr, $define, $compp, $set, $parm2);

	$compr = ""; $parm2 = ""; $define = "";
	$compr = "    int cmp; \\\n" unless $i == 1;
	$compp = "";
	$set = "";

	foreach my $j (1..$i) {
		if ($j != $i) {
			$compr .= "    cmp = mysqlpp::sql_cmp(x.C$j , y.C$j ); \\\n";
			$compr .= "    if (cmp) return cmp; \\\n";
		}

		$compr .= "    return mysqlpp::sql_cmp(x.C$j , y.C$j );" if $j == $i;
		$parm2 .= "const T$j &p$j";
		$parm2 .= ", " unless $j == $i;
		$define.= "C$j (p$j)";
		$define.= ", " unless $j == $i;
		$set   .= "    C$j = p$j;\\\n";
		$compp .= "true";
		$compp .= ", " unless $j == $i;
	}
	print OUT << "---";

// ---------------------------------------------------
//                   Begin Compare $i
// ---------------------------------------------------

#define sql_compare_define_$i(NAME, $parm0) \\
	NAME($parm2) : $define, table_override_(0) {} \\
	void set($parm2) { \\
	table_override_ = 0; \\
$set \\
	} \\
	sql_compare_define(NAME)

#define sql_construct_define_$i(NAME, $parm0) \\
	void set($parm2) { \\
	table_override_ = 0; \\
$set \\
	} \\
	NAME($parm2) : $define, table_override_(0) {}

#define sql_compare_type_def_$i(NAME, WHAT, NUM) \\
	return WHAT##_list(d, m, $compp)

#define sql_compare_type_defe_$i(NAME, WHAT, NUM) \\
	return WHAT##_list(d, c, m, $compp)

#define sql_COMPARE__$i(NAME, $parm1) \\
	template <mysqlpp::sql_dummy_type dummy> \\
	int sql_compare_##NAME(const NAME &x, const NAME &y) { \\
$compr \\
	} \\
	template <mysqlpp::sql_dummy_type dummy> \\
	int compare (const NAME &x, const NAME &y) { \\
$compr \\
	}

// ---------------------------------------------------
//                   End Compare $i
// ---------------------------------------------------

---
}


foreach my $i (1..$max_data_members) {
	my $create_bool = "";
	my $create_list = "";
	my $cus_equal_list = "";
	my $cus_field_list = "";
	my $cusparms1 = "";
	my $cusparms11 = "";
	my $cusparms2 = "";
	my $cusparms22 = "";
	my $cusparmsv = "";
	my $defs = "";
	my $enums = "";
	my $equal_list = "";
	my $field_list = "";
	my $names = "";
	my $parmc = "";
	my $parmC = "";
	my $parm_complete = "";
	my $parm_simple = "";
	my $parm_simple2c = "";
	my $parm_simple2c_b = "";
	my $parm_simple_b = "";
	my $popul = "";
	my $value_list = "";
	my $value_list_cus = "";

	foreach my $j (1 .. $i) {
		$parm_complete .= "T$j, I$j, N$j";
		$parm_complete .= ", " unless $j == $i;
		$parm_simple   .= "T$j, I$j";
		$parm_simple   .= ", " unless $j == $i;
		$parm_simple2c .= "T$j, I$j, #I$j";
		$parm_simple2c .= ", " unless $j == $i;
		$parm_simple_b   .= "T$j, I$j";
		$parm_simple_b   .= ", " unless $j == $i;
		$parm_simple2c_b .= "T$j, I$j";
		$parm_simple2c_b .= ", " unless $j == $i;

		$defs  .= "    T$j I$j;";
		$defs  .= "\n" unless $j == $i;

		$popul .= "    s->I$j = row[N$j].conv(T$j());";
		$popul .= "\n" unless $j == $i;

		$names .= "    N$j ";
		$names .= ",\n" unless $j == $i;
		$enums .= "    NAME##_##I$j";
		$enums .= ",\n" unless $j == $i;

		$field_list .= "    s << obj.manip << obj.obj->names[".($j-1)."]";
		$field_list .= " << obj.delim;\n" unless $j == $i;

		$value_list .= "    s << obj.manip << obj.obj->I$j";
		$value_list .= " << obj.delim;\n" unless $j == $i;

		$create_bool .= "    if (i$j) (*include)[".($j-1)."]=true;\n";

		$create_list .= "    if (i$j == NAME##_NULL) return;\n" unless $i == 1;
		$create_list .= "    (*include)[i$j]=true;\n";

		$value_list_cus .= "    if ((*obj.include)[".($j-1)."]) { \n";
		$value_list_cus .= "      if (before) s << obj.delim;\n" unless $j == 1;
		$value_list_cus .= "      s << obj.manip << obj.obj->I$j;\n";
		$value_list_cus .= "      before = true; \n" unless $j == $i;
		$value_list_cus .= "     } \n";

		$cus_field_list .= "    if ((*obj.include)[".($j-1)."]) { \n";
		$cus_field_list .= "      if (before) s << obj.delim;\n" unless $j == 1;
		$cus_field_list .= "      s << obj.manip << obj.obj->names[".($j-1)."];\n";
		$cus_field_list .= "      before = true; \n" unless $j == $i;
		$cus_field_list .= "     } \n";

		$cus_equal_list .= "    if ((*obj.include)[".($j-1)."]) { \n";
		$cus_equal_list .= "      if (before) s << obj.delim;\n" unless $j == 1;
		$cus_equal_list .= "      s << obj.obj->names[".($j-1)."] << obj.comp";
		$cus_equal_list .=        " << obj.manip << obj.obj->I$j;\n";
		$cus_equal_list .= "      before = true; \n" unless $j == $i;
		$cus_equal_list .= "     } \n";

		$equal_list .= "    s << obj.obj->names[".($j-1)."] << obj.comp";
		$equal_list .= " << obj.manip << obj.obj->I$j";
		$equal_list .= " << obj.delim;\n" unless $j == $i;

		$cusparms1  .= "bool i$j"         if     $j == 1;
		$cusparms1  .= "bool i$j = false" unless $j == 1;
		$cusparms1  .= ", " unless $j == $i;
		$cusparms11  .= "bool i$j" ;
		$cusparms11  .= ", " unless $j == $i;
		$cusparms2  .= "NAME##_enum i$j" if $j == 1;
		$cusparms2  .= "NAME##_enum i$j = NAME##_NULL" unless $j == 1;
		$cusparms2  .= ", " unless $j == $i;
		$cusparms22  .= "NAME##_enum i$j";
		$cusparms22  .= ", " unless $j == $i;
		$cusparmsv  .= "i$j";
		$cusparmsv  .= ", " unless $j == $i;

		$parmC .= "T$j, I$j";
		$parmC .= ", " unless $j == $max_data_members;
		$parmc .= "I$j";
		$parmc .= ", " unless $j == $max_data_members;
	}

	foreach my $j ($i + 1 .. $max_data_members) {
		$parmC .= "0, 0";
		$parmC .= ", " unless $j == $max_data_members;
		$parmc .= "0";
		$parmc .= ", " unless $j == $max_data_members;
	}

	print OUT << "---";
// ---------------------------------------------------
//                  Begin Create $i
// ---------------------------------------------------
---
	my $out = <<"---";
#define sql_create_complete_$i(NAME, CMP, CONTR, $parm_complete) 
	struct NAME; 




	enum NAME##_enum { 
$enums 
	,NAME##_NULL 
	}; 

	template <class Manip>
	class NAME##_value_list { 
	public: 
	const NAME* obj;
	const char* delim;
	Manip manip;
	public: 
	NAME##_value_list (const NAME* o, const char* d, Manip m) :
	obj(o), delim(d), manip(m) { } 
	};

	template <class Manip>
	class NAME##_##field_list {
	public: 
	const NAME* obj; 
	const char* delim;
	Manip manip;
	public: 
	NAME##_field_list (const NAME* o, const char* d, Manip m) :
	obj(o), delim(d), manip(m) { } 
	};

	template <class Manip>
	class NAME##_equal_list { 
	public: 
	const NAME* obj;
	const char* delim;
	const char* comp;
	Manip manip;

	public: 
	NAME##_equal_list (const NAME* o, const char* d, const char* c, Manip m) :
	obj(o), delim(d), comp(c), manip(m) { }
	};

	template <class Manip>
	class NAME##_cus_value_list {
	public:
	const NAME* obj;
	std::vector<bool> *include;
	bool del_vector;
	const char* delim;
	Manip manip;
	public: 
	~NAME##_cus_value_list () {if (del_vector) delete include;} 
	NAME##_cus_value_list (const NAME* o, const char* d, Manip m, $cusparms11);
	NAME##_cus_value_list (const NAME* o, const char* d, Manip m, $cusparms22); 
	NAME##_cus_value_list (const NAME* o, const char* d, Manip m ,std::vector<bool>* i) :
	obj(o), include(i), del_vector(false), delim(d), manip(m) { }
	};

	template <class Manip>
	class NAME##_cus_field_list { 
	public:
	const NAME* obj; 
	std::vector<bool> *include; 
	bool del_vector; 
	const char* delim;
	Manip manip;
	public: 
	~NAME##_cus_field_list () {if (del_vector) delete include;} 
	NAME##_cus_field_list (const NAME* o, const char* d, Manip m, $cusparms11); 
	NAME##_cus_field_list (const NAME* o, const char* d, Manip m, $cusparms22); 
	NAME##_cus_field_list (const NAME* o, const char* d, Manip m, std::vector<bool> *i) :
	obj(o), include(i), del_vector(false), delim(d), manip(m) { }
	};

	template <class Manip>
	class NAME##_cus_equal_list {
	public:
	const NAME* obj;
	std::vector<bool> *include;
	bool del_vector;
	const char* delim;
	const char* comp;
	Manip manip;
	public:
	~NAME##_##cus_equal_list () {if (del_vector) delete include;}
	NAME##_##cus_equal_list (const NAME* o, const char* d, const char* c, Manip m, $cusparms11); 
	NAME##_##cus_equal_list (const NAME* o, const char* d, const char* c, Manip m, $cusparms22); 
	NAME##_##cus_equal_list (const NAME* o, const char* d, const char* c, Manip m, std::vector<bool> *i) :
	obj(o), include(i), del_vector(false), delim(d), comp(c), manip(m) { }
	};

	template <mysqlpp::sql_dummy_type dummy> int sql_compare_##NAME(const NAME&, const NAME&);

	struct NAME {
$defs 
	NAME() : table_override_(0) { }
	NAME(const mysqlpp::Row& row);
	void set(const mysqlpp::Row &row);
	sql_compare_define_##CMP(NAME, $parmC)
	sql_construct_define_##CONTR(NAME, $parmC)
	static const char* names[];
	static void table(const char* t) { table_ = t; }
	const char* const table() const
			{ return table_override_ ? table_override_ : NAME::table_; }
	void instance_table(const char* t) { table_override_ = t; }

	NAME##_value_list<mysqlpp::quote_type0> value_list() const {
		return value_list(",", mysqlpp::quote);}
	NAME##_value_list<mysqlpp::quote_type0> value_list(const char* d) const {
		return value_list(d, mysqlpp::quote);}
	template <class Manip>
	NAME##_value_list<Manip> value_list(const char* d, Manip m) const;

	NAME##_field_list<mysqlpp::do_nothing_type0> field_list() const {
		return field_list(",", mysqlpp::do_nothing);}
	NAME##_field_list<mysqlpp::do_nothing_type0> field_list(const char* d) const {
		return field_list(d, mysqlpp::do_nothing);}
	template <class Manip>
	NAME##_field_list<Manip> field_list(const char* d, Manip m) const;

	NAME##_equal_list<mysqlpp::quote_type0> equal_list(const char* d = ",",
			const char* c = " = ") const
			{ return equal_list(d, c, mysqlpp::quote); }
	template <class Manip>
	NAME##_equal_list<Manip> equal_list(const char* d, const char* c, Manip m) const;

	/* cus_data */

	NAME##_cus_value_list<mysqlpp::quote_type0> value_list($cusparms1) const
			{ return value_list(",", mysqlpp::quote, $cusparmsv); }
	NAME##_cus_value_list<mysqlpp::quote_type0> value_list($cusparms2) const
			{ return value_list(",", mysqlpp::quote, $cusparmsv); }
	NAME##_cus_value_list<mysqlpp::quote_type0> value_list(std::vector<bool> *i) const
			{ return value_list(",", mysqlpp::quote, i); }
	NAME##_cus_value_list<mysqlpp::quote_type0> value_list(mysqlpp::sql_cmp_type sc) const
			{ return value_list(",", mysqlpp::quote, sc); }

	NAME##_cus_value_list<mysqlpp::quote_type0> value_list(const char* d, $cusparms1) const
			{ return value_list(d, mysqlpp::quote, $cusparmsv); }
	NAME##_cus_value_list<mysqlpp::quote_type0> value_list(const char* d, $cusparms2) const
			{ return value_list(d, mysqlpp::quote, $cusparmsv); }
	NAME##_cus_value_list<mysqlpp::quote_type0> value_list(const char* d,
			std::vector<bool> *i) const
			{ return value_list(d, mysqlpp::quote, i); }
	NAME##_cus_value_list<mysqlpp::quote_type0> value_list(const char* d,
			mysqlpp::sql_cmp_type sc) const
			{ return value_list(d, mysqlpp::quote, sc); }

	template <class Manip>
	NAME##_cus_value_list<Manip> value_list(const char* d, Manip m,
			$cusparms1) const;
	template <class Manip>
	NAME##_cus_value_list<Manip> value_list(const char* d, Manip m,
			$cusparms2) const;
	template <class Manip>
	NAME##_cus_value_list<Manip> value_list(const char* d, Manip m,
			std::vector<bool>* i) const;
	template <class Manip>
	NAME##_cus_value_list<Manip> value_list(const char* d, Manip m, 
			mysqlpp::sql_cmp_type sc) const;
	/* cus field */

	NAME##_cus_field_list<mysqlpp::do_nothing_type0> field_list($cusparms1) const 
			{ return field_list(",", mysqlpp::do_nothing, $cusparmsv); }
	NAME##_cus_field_list<mysqlpp::do_nothing_type0> field_list($cusparms2) const
			{ return field_list(",", mysqlpp::do_nothing, $cusparmsv); }
	NAME##_cus_field_list<mysqlpp::do_nothing_type0> field_list(std::vector<bool> *i) const
			{ return field_list(",", mysqlpp::do_nothing, i); }
	NAME##_cus_field_list<mysqlpp::do_nothing_type0> field_list(mysqlpp::sql_cmp_type sc) const
			{ return field_list(",", mysqlpp::do_nothing, sc); }

	NAME##_cus_field_list<mysqlpp::do_nothing_type0> field_list(const char* d,
			$cusparms1) const
			{ return field_list(d, mysqlpp::do_nothing, $cusparmsv); }
	NAME##_cus_field_list<mysqlpp::do_nothing_type0> field_list(const char* d,
			$cusparms2) const
			{ return field_list(d, mysqlpp::do_nothing, $cusparmsv); }
	NAME##_cus_field_list<mysqlpp::do_nothing_type0> field_list(const char* d,
			std::vector<bool>* i) const
			{ return field_list(d, mysqlpp::do_nothing, i); }
	NAME##_cus_field_list<mysqlpp::do_nothing_type0> field_list(const char* d,
			mysqlpp::sql_cmp_type sc) const
			{ return field_list(d, mysqlpp::do_nothing, sc); }

	template <class Manip>
	NAME##_cus_field_list<Manip> field_list(const char* d, Manip m,
			$cusparms1) const;
	template <class Manip>
	NAME##_cus_field_list<Manip> field_list(const char* d, Manip m,
			$cusparms2) const;
	template <class Manip>
	NAME##_cus_field_list<Manip> field_list(const char* d, Manip m,
			std::vector<bool> *i) const;
	template <class Manip>
	NAME##_cus_field_list<Manip> field_list(const char* d, Manip m,
			mysqlpp::sql_cmp_type sc) const;

	/* cus equal */

	NAME##_cus_equal_list<mysqlpp::quote_type0> equal_list($cusparms1) const
			{ return equal_list(",", " = ", mysqlpp::quote, $cusparmsv); }
	NAME##_cus_equal_list<mysqlpp::quote_type0> equal_list($cusparms2) const
			{ return equal_list(",", " = ", mysqlpp::quote, $cusparmsv); }
	NAME##_cus_equal_list<mysqlpp::quote_type0> equal_list(std::vector<bool>* i) const
			{ return equal_list(",", " = ", mysqlpp::quote, i); }
	NAME##_cus_equal_list<mysqlpp::quote_type0> equal_list(mysqlpp::sql_cmp_type sc) const
			{ return equal_list(",", " = ", mysqlpp::quote, sc); }

	NAME##_cus_equal_list<mysqlpp::quote_type0> equal_list(const char* d, $cusparms1) const
			{ return equal_list(d, " = ", mysqlpp::quote, $cusparmsv); }
	NAME##_cus_equal_list<mysqlpp::quote_type0> equal_list(const char* d, $cusparms2) const
			{ return equal_list(d, " = ", mysqlpp::quote, $cusparmsv); }
	NAME##_cus_equal_list<mysqlpp::quote_type0> equal_list(const char* d,
			std::vector<bool> *i) const
			{ return equal_list(d, " = ", mysqlpp::quote, i); }
	NAME##_cus_equal_list<mysqlpp::quote_type0> equal_list(const char* d,
			mysqlpp::sql_cmp_type sc) const
			{ return equal_list(d, " = ", mysqlpp::quote, sc); }

	NAME##_cus_equal_list<mysqlpp::quote_type0> equal_list(const char* d, const char* c,
			$cusparms1) const
			{ return equal_list(d, c, mysqlpp::quote, $cusparmsv); }
	NAME##_cus_equal_list<mysqlpp::quote_type0> equal_list(const char* d, const char* c,
			$cusparms2) const
			{ return equal_list(d, c, mysqlpp::quote, $cusparmsv); }
	NAME##_cus_equal_list<mysqlpp::quote_type0> equal_list(const char* d, const char* c,
			std::vector<bool> *i) const
			{ return equal_list(d, c, mysqlpp::quote, i); }
	NAME##_cus_equal_list<mysqlpp::quote_type0> equal_list(const char* d, const char* c,
			mysqlpp::sql_cmp_type sc) const
			{ return equal_list(d, c, mysqlpp::quote, sc); }

	template <class Manip>
	NAME##_cus_equal_list<Manip> equal_list(const char* d, const char* c, Manip m, 
						$cusparms1) const;
	template <class Manip>
	NAME##_cus_equal_list<Manip> equal_list(const char* d, const char* c, Manip m, 
						$cusparms2) const;
	template <class Manip>
	NAME##_cus_equal_list<Manip> equal_list(const char* d, const char* c, Manip m, 
						std::vector<bool> *i) const;
	template <class Manip>
	NAME##_cus_equal_list<Manip> equal_list(const char* d, const char* c, Manip m, 
						mysqlpp::sql_cmp_type sc) const;

	private:
	static const char* table_;
	const char* table_override_;
	};
	MYSQLPP_SSQLS_CONDITIONAL_STATICS(
		const char* NAME::names[] = {
			$names
		};
		const char* NAME::table_ = #NAME;
	)

	template <class Manip>
	NAME##_cus_value_list<Manip>::NAME##_cus_value_list
			(const NAME* o, const char* d, Manip m, $cusparms11)
	{
		delim = d;
		manip = m;
		del_vector = true;
		obj = o;
		include = new std::vector<bool>($i, false);
$create_bool
	}

	template <class Manip>
	NAME##_cus_value_list<Manip>::NAME##_cus_value_list
			(const NAME* o, const char* d, Manip m, $cusparms22)
	{
		delim = d;
		manip = m;
		del_vector = true;
		obj = o;
		include = new std::vector<bool>($i, false);
$create_list
	}

	template <class Manip>
	NAME##_cus_field_list<Manip>::NAME##_cus_field_list
			(const NAME* o, const char* d, Manip m, $cusparms11)
	{
		delim = d;
		manip = m;
		del_vector = true;
		obj = o;
		include = new std::vector<bool>($i, false);
$create_bool
	}

	template <class Manip>
	NAME##_cus_field_list<Manip>::NAME##_cus_field_list
			(const NAME* o, const char* d, Manip m, $cusparms22)
	{
		delim = d;
		manip = m;
		del_vector = true;
		obj = o;
		include = new std::vector<bool>($i, false);
$create_list
	}

	template <class Manip>
	NAME##_cus_equal_list<Manip>::NAME##_cus_equal_list
			(const NAME* o, const char* d, const char* c, Manip m, $cusparms11)
	{
		delim = d;
		comp = c;
		manip = m;
		del_vector = true;
		obj = o;
		include = new std::vector<bool>($i, false);
$create_bool
	}

	template <class Manip>
	NAME##_cus_equal_list<Manip>::NAME##_cus_equal_list
			(const NAME* o, const char* d, const char* c, Manip m, $cusparms22)
	{
		delim = d;
		comp = c;
		manip = m;
		del_vector = true;
		obj = o;
		include = new std::vector<bool>($i, false);
$create_list
	}

	template <class Manip>
	std::ostream& operator <<(std::ostream& s, const NAME##_value_list<Manip>& obj)
	{
$value_list;
		return s;
	}

	template <class Manip>
	std::ostream& operator <<(std::ostream& s, const NAME##_field_list<Manip>& obj)
	{
$field_list;
		return s;
	}

	template <class Manip>
	std::ostream& operator <<(std::ostream& s, const NAME##_equal_list<Manip>& obj)
	{
$equal_list;
		return s;
	}

	template <class Manip>
	std::ostream& operator <<(std::ostream& s, const NAME##_cus_value_list<Manip>& obj)
	{
		bool before = false;
$value_list_cus
		return s;
	}

	template <class Manip>
	std::ostream& operator <<(std::ostream& s, const NAME##_cus_field_list<Manip>& obj)
	{
		bool before = false;
$cus_field_list
		return s;
	}

	template <class Manip>
	std::ostream& operator <<(std::ostream& s, const NAME##_cus_equal_list<Manip>& obj)
	{
		bool before = false;
$cus_equal_list
		return s;
	}

	template <class Manip>
	inline NAME##_value_list<Manip> NAME::value_list(const char* d, Manip m) const
			{ return NAME##_value_list<Manip> (this, d, m); } 

	template <class Manip>
	inline NAME##_field_list<Manip> NAME::field_list(const char* d, Manip m) const
			{ return NAME##_field_list<Manip> (this, d, m); } 

	template <class Manip>
	inline NAME##_equal_list<Manip> NAME::equal_list(const char* d, const char* c, Manip m) const
			{ return NAME##_equal_list<Manip> (this, d, c, m); } 

	template <class Manip>
	inline NAME##_cus_value_list<Manip> NAME::value_list(const char* d, Manip m,
			$cusparms11) const
			{ return NAME##_cus_value_list<Manip> (this, d, m, $cusparmsv); }

	template <class Manip>
	inline NAME##_cus_field_list<Manip> NAME::field_list(const char* d, Manip m,
			$cusparms11) const
			{ return NAME##_cus_field_list<Manip> (this, d, m, $cusparmsv); }

	template <class Manip>
	inline NAME##_cus_equal_list<Manip> NAME::equal_list(const char* d, const char* c, Manip m,
			$cusparms11) const
			{ return NAME##_cus_equal_list<Manip> (this, d, c, m, $cusparmsv); } 

	template <class Manip>
	inline NAME##_cus_value_list<Manip> NAME::value_list(const char* d, Manip m,
			$cusparms22) const
			{ return NAME##_cus_value_list<Manip> (this, d, m, $cusparmsv); } 

	template <class Manip>
	inline NAME##_cus_field_list<Manip> NAME::field_list(const char* d, Manip m,
			$cusparms22) const
			{ return NAME##_cus_field_list<Manip> (this, d, m, $cusparmsv); } 

	template <class Manip>
	inline NAME##_cus_equal_list<Manip> NAME::equal_list(const char* d, const char* c, Manip m, 
			$cusparms22) const
			{ return NAME##_cus_equal_list<Manip> (this, d, c, m, $cusparmsv); } 

	template <class Manip>
	inline NAME##_cus_value_list<Manip> NAME::value_list(const char* d, Manip m,
			std::vector<bool> *i) const
			{ return NAME##_cus_value_list<Manip> (this, d, m, i); }

	template <class Manip>
	inline NAME##_cus_field_list<Manip> NAME::field_list(const char* d, Manip m,
			std::vector<bool> *i) const
			{ return NAME##_cus_field_list<Manip> (this, d, m, i); }

	template <class Manip>
	inline NAME##_cus_equal_list<Manip> NAME::equal_list(const char* d, const char* c, Manip m,
			std::vector<bool> *i) const
			{ return NAME##_cus_equal_list<Manip> (this, d, c, m, i); }

	template <class Manip>
	inline NAME##_cus_value_list<Manip> 
	NAME::value_list(const char* d, Manip m, mysqlpp::sql_cmp_type /*sc*/) const
			{ sql_compare_type_def_##CMP(NAME, value, NUM); }

	template <class Manip>
	inline NAME##_cus_field_list<Manip> 
	NAME::field_list(const char* d, Manip m, mysqlpp::sql_cmp_type /*sc*/) const
			{ sql_compare_type_def_##CMP(NAME, field, NUM); }

	template <class Manip>
	inline NAME##_cus_equal_list<Manip> 
	NAME::equal_list(const char* d, const char* c, Manip m, mysqlpp::sql_cmp_type /*sc*/) const
			{ sql_compare_type_defe_##CMP(NAME, equal, NUM); }

	template <mysqlpp::sql_dummy_type dummy>
	void populate_##NAME(NAME *s, const mysqlpp::Row &row)
	{
		mysqlpp::NoExceptions ignore_schema_mismatches(row);
$popul
	}

	inline NAME::NAME(const mysqlpp::Row& row) :
	table_override_(0)
			{ populate_##NAME<mysqlpp::sql_dummy>(this, row); }
	inline void NAME::set(const mysqlpp::Row& row)
	{
		table_override_ = 0;
		populate_##NAME<mysqlpp::sql_dummy>(this, row);
	}

	sql_COMPARE__##CMP(NAME, $parmc )

---
print OUT &prepare($out);

#
# short cut defs
#

print OUT << "---";
#define sql_create_$i(NAME, CMP, CONTR, $parm_simple) \\
		sql_create_complete_$i(NAME, CMP, CONTR, $parm_simple2c) \\

// ---------------------------------------------------
//                  End Create $i
// ---------------------------------------------------

---

}


print OUT << "---";

} // end namespace mysqlpp

#endif // !defined(MYSQLPP_SSQLS_H)

---


sub prepare {
	local $_ = $_[0];
	s/\n+$//;
	s/\n[\n ]*\n/\n/g; 
	s/\n+/\\\n/g;
	$_ .= "\n\n";
	return $_;
}

Changes to exrun.bat.



1



2

3




4




5





6

7


8

9

10













11

12
13














14































@echo off



set PROG=%1

if not exist %PROG% set PROG=%1.exe




if not exist %PROG% set PROG=Debug\%1




if not exist %PROG% set PROG=vc2008\x64\Debug\%1.exe





if not exist %PROG% set PROG=vc2008\Debug\%1.exe

if not exist %PROG% set PROG=vc2005\Debug\%1.exe


if not exist %PROG% set PROG=vc2003\Debug\%1.exe

if not exist %PROG% exit

shift















set PATH=Debug;vc2008\x64\Debug;vc2008\Debug;vc2005\Debug;vc2003\Debug;%PATH%
echo Running %PROG%...














%PROG% %1 %2 %3 %4 %5 %6 %7 %8 %9





























>
>
|
>
>
>
|
>
|
>
>
>
>
|
>
>
>
>
|
>
>
>
>
>
|
>
|
>
>
|
>
|
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
|
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
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
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
/***********************************************************************
 sqlstream.cpp - Implements the SQLStream class.

 Copyright (c) 2008 by AboveNet, Inc.  Others may also hold copyrights 
 on code in this file.  See the CREDITS file in the top directory of 
 the distribution for details.

 This file is part of MySQL++.

 MySQL++ is free software; you can redistribute it and/or modify it
 under the terms of the GNU Lesser General Public License as published
 by the Free Software Foundation; either version 2.1 of the License, or
 (at your option) any later version.

 MySQL++ is distributed in the hope that it will be useful, but WITHOUT
 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
 License for more details.

 You should have received a copy of the GNU Lesser General Public
 License along with MySQL++; if not, write to the Free Software
 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
 USA
***********************************************************************/

#include "sqlstream.h"

#include "dbdriver.h"
#include "connection.h"

#include <string>

namespace mysqlpp {

SQLStream::SQLStream(Connection* c, const char* pstr) :
std::ostringstream(),
conn_(c)
{
	if (pstr != 0) {
		str(pstr);
	}
}


SQLStream::SQLStream(const SQLStream& s) :
std::ostringstream(s.str()),
conn_(s.conn_)
{
}


size_t
SQLStream::escape_string(std::string* ps, const char* original,
		size_t length) const
{
	if (conn_ && *conn_) {
		// Normal case
		return conn_->driver()->escape_string(ps, original, length);
	}
	else {
		// Should only happen in test/test_manip.cpp, since it doesn't
		// want to open a DB connection just to test the manipulators.
		return DBDriver::escape_string_no_conn(ps, original, length);
	}
}


size_t
SQLStream::escape_string(char* escaped, const char* original,
		size_t length) const
{
	if (conn_ && *conn_) {
		// Normal case
		return conn_->driver()->escape_string(escaped, original, length);
	}
	else {
		// Should only happen in test/test_manip.cpp, since it doesn't
		// want to open a DB connection just to test the manipulators.
		return DBDriver::escape_string_no_conn(escaped, original, length);
	}
}


SQLStream&
SQLStream::operator=(const SQLStream& rhs)
{
	conn_ = rhs.conn_;
	str(rhs.str());

	return *this;
}


} // end namespace mysqlpp

Changes to install.hta.in.

1

2
3
4

5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
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
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
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
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
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
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
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
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
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
372
<?xml version="1.0" encoding="UTF-8"?>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
		"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<!--

 install.hta - GUI installer for Windows systems, using Microsoft's
		HTML Application technology.  Tested on XP with IE7.  May
		work on systems as old as Win9x with IE4.

 For all other platforms, use "make install".

 Copyright (c) 2008 by Educational Technology Resources, Inc. and
 Warren Young.  Others may also hold copyrights on code in this file.
 See the CREDITS file in the top folder of the distribution for details.

 This file is part of MySQL++.

 MySQL++ is free software; you can redistribute it and/or modify it
 under the terms of the GNU Lesser General Public License as published
 by the Free Software Foundation; either version 2.1 of the License, or
 (at your option) any later version.

 MySQL++ is distributed in the hope that it will be useful, but WITHOUT
 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
 License for more details.

 You should have received a copy of the GNU Lesser General Public
 License along with MySQL++; if not, write to the Free Software
 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
 USA
-->
<html xmlns="http://www.w3.org/1999/xhtml">
	<head>
		<title>Install MySQL++ Development Files</title>

		<hta:application
			applicationname="mysqlppInstaller"
			borderstyle="raised"
			innerborder="no"
			scroll="no"
			singleinstance="yes"
			sysmenu="no"/>

		<style type="text/css">
			body {
				background-color: buttonface;
				margin: 10px;
			}

			body, button, input, select, td {
				font-family: Trebuchet MS, Helvetica;
				font-size: 10pt;
			}

			input.status {
				background-color: buttonface;
				border: none;
			}
		</style>

		<script type="text/javascript">
			function $(id) { return document.getElementById(id); }
		</script>

		<script type="text/javascript">
			var c = '';
			var fso = new ActiveXObject('Scripting.FileSystemObject');
			var folderList, driveList, installTargetField, segregateManagedBox,
				segregatePlatformBox, versionedFolderBox;
			var managedBuild = false;

			// Copies a file under a given prefix folder to another folder
			// given as a subfolder under some fixed prefix folder,
			// creating the whole folder path if needed, if it doesn't exist.
			// Skips prefix prepending if prefix is null.  Skips folder
			// creation if source file doesn't exist.
			function copyFile(filePrefix, file, dirPrefix, destSubDir)
			{
				var src = filePrefix ? fso.BuildPath(filePrefix, file) : file;
				if ((!filePrefix || fso.FolderExists(filePrefix)) && 
						((src.indexOf('*') != -1) || fso.FileExists(src))) {
					var dst = createFolderRecursive(
							dirPrefix ? fso.BuildPath(dirPrefix, destSubDir) : destSubDir);
					try {
						fso.CopyFile(src, dst);
					}
					catch (e) {
						alert('Failed to copy ' + file + ' to ' + baseInstallFolder + ': ' +
								e.message + '\n\nInstallation aborted!');
						window.close();
					}
				}
			}

			// Creates a folder if it doesn't already exist.  If creation
			// attempt fails, puts up alert dialog explaining the problem and
			// quits program.
			function createFolder(d)
			{
				if (!fso.FolderExists(d)) {
					try {
						fso.CreateFolder(d);
					}
					catch (e) {
						alert('Failed to create ' + d + ' folder: ' +
								e.message + '\n\nInstallation aborted!');
						window.close();
					}
				}
			}

			// Like createFolder(), but will create parent directories as
			// needed.  Returns d, normalized.
			function createFolderRecursive(d)
			{
				var i, dir = '', dirElements = d.split('\\');
				for (i = 0; i < dirElements.length; ++i) {
					dir += dirElements[i] + '\\';
					createFolder(dir);
				}
				return dir;
			}

			// Called when app is fully loaded, so initialize ourselves.
			function init()
			{
				// Set initial window size
				window.resizeTo(600, 390);

				// Get references to main UI elements
				folderList = $('folder');
				driveList = $('drive');
				installTargetField = $('installTarget');
				segregateManagedBox = $('segregateManaged');
				segregatePlatformBox = $('segregatePlatform');
				versionedFolderBox = $('versionedFolder');

				// Populate drop-down list of available drives
				populateDriveList();

				// Populate list of directories on the current drive
				populateFolderList();

				// Now that we have drive and folder lists, set initial value
				// for installation folder from default list selections.
				updateInstallFolder();

				// Set up UI event handlers.  We put it off to this point so
				// UI is populated before first handler gets called.
				driveList.onchange = function() {
					populateFolderList();
					updateInstallFolder();
				}
				folderList.onchange = segregateManagedBox.onclick =
						versionedFolderBox.onclick = updateInstallFolder;
			}

			// Do the actual installation
			function install()
			{
				var i, destSubDir, srcDir;
				var usePlatform = segregatePlatformBox.checked;
				var versions = [ '3', '5', '8' ], version;
				
				// Install header files
				copyFile('lib', '*.h', baseInstallFolder, 'include');

				// Install MinGW library build, if it exists
				destSubDir = 'lib' + (usePlatform ? '\\MinGW' : '');
				copyFile(null, 'libmysqlpp.a', baseInstallFolder, destSubDir);
				copyFile(null, 'mysqlpp.dll', baseInstallFolder, destSubDir);

				// Install any and all existing VC++ library builds
				for (i = 0; i < versions.length; ++i) {
					version = 'vc200' + versions[i];
					destSubDir = 'lib' + 
							(usePlatform ? '\\VC++ 200' + versions[i] : '');
					if (segregateManagedBox.checked) {
						destSubDir += '\\' + (isManagedBuild(version) ?
								'CLR' : 'Native');
					}
					
					srcDir = version + '\\Debug';
					copyFile(srcDir, 'mysqlpp_d.dll', baseInstallFolder, destSubDir);
					copyFile(srcDir, 'mysqlpp_d.lib', baseInstallFolder, destSubDir);
					
					srcDir = version + '\\Release';
					copyFile(srcDir, 'mysqlpp.dll', baseInstallFolder, destSubDir);
					copyFile(srcDir, 'mysqlpp.lib', baseInstallFolder, destSubDir);
				}

				window.close();
			}
			
			// Returns true if the MySQL++ library for the given VC++
			// version was built for use with the CLR.
			function isManagedBuild(version)
			{
				var stream = fso.OpenTextFile(
						version + '\\mysql++_mysqlpp.vcproj');
				if (stream) {
					var mloc = stream.ReadAll().indexOf('ManagedExtensions="1"');
					stream.Close();
					return mloc > 0;
				}
				else {
					return false;
				}
			}

			// Populates a drop-down list with the set of fixed disks and
			// removable drives with media in them.
			function populateDriveList()
			{
				var defLetter = 'C';
				var e, i, letter, name;

				for (e = new Enumerator(fso.Drives); !e.atEnd(); e.moveNext()) {
					i = e.item();
					if (i.IsReady) {
						letter = i.DriveLetter;
						name = letter + ': - ';

						if ((i.DriveType == 3) && 
								i.ShareName.length) {
							name += i.ShareName;
						}
						else if ((i.DriveType != 3) &&
								i.VolumeName.length) {
							name += i.VolumeName;
						}
						else {
							name += '(no name)';
						}

						driveList.add(new Option(name, letter,
								letter == defLetter, letter == defLetter));
					}
				}
			}

			// Populates a list box with the top-level directories on the
			// currently-selected disk drive.
			function populateFolderList()
			{
				var driveRoot =
						driveList.options[driveList.selectedIndex].value + ':\\';
				var e, f = fso.GetFolder(driveRoot);
				if (f) {
					folderList.options.length = 0;
					folderList.add(new Option(driveRoot, driveRoot, true, true));
					for (e = new Enumerator(f.SubFolders); !e.atEnd(); e.moveNext()) {
						folderList.add(new Option(e.item() + '\\'));
					}
				}
				else {
					alert('Failed to get folder list for ' + driveRoot);
				}
			}

			// On clicking the text label associated with "versioned install
			// folder" checkbox, toggle checkbox and update UI.
			function toggleVersioning()
			{
				if (versionedFolderBox) {
					versionedFolderBox.checked = !versionedFolderBox.checked;
					updateInstallFolder();
				}
			}

			// On clicking the text label associated with a checkbox, toggle
			// checkbox state and update UI.
			function toggleCheckbox(boxID)
			{
				var box = $(boxID);
				if (box) {
					box.checked = !box.checked;
					updateInstallFolder();
				}
			}

			// Called any time something changes that affects how we calculate
			// the installation folder name.  Rebuilds it.
			function updateInstallFolder()
			{
				baseInstallFolder =
						folderList.options[folderList.selectedIndex].text +
						'MySQL++' +
						(versionedFolderBox.checked ? '\\@PACKAGE_VERSION@' : '');
				installTargetField.value =
						baseInstallFolder +
						'\\{include,lib' +
						(segregatePlatformBox.checked ? '\\PLATFORM' : '') +
						(segregateManagedBox.checked ? '\\{CLR,Native}' : '') +
						'}';
			}
		</script>
	</head>
	
	<body onload="init()">
		<p>
			Where would you like to install the MySQL++ development
			files?<br/>

			<table cellspacing="10" cellpadding="0" border="0" width="100%"
					summary="">
				<tr>
					<td align="right" valign="middle">Drives:</td>
					<td width="99%">
						<select id="drive">
						</select>
					</td>
				</tr>

				<tr>
					<td align="right" valign="top">Folders:</td>
					<td width="99%">
						<select id="folder" size="6">
						</select>
					</td>
				</tr>

				<tr>
					<td>&nbsp;</td>
					<td>
						<input type="checkbox" id="versionedFolder"/> 
						<span style="cursor: default"
								onclick="toggleCheckbox('versionedFolder')">Install
								in versioned folder?</span>
					</td>
				</tr>

				<tr>
					<td>&nbsp;</td>
					<td>
						<input type="checkbox" id="segregateManaged"/> 
						<span style="cursor: default"
							onclick="toggleCheckbox('segregateManaged')">Segregate
							native C++ library builds from C++/CLI (CLR)
							builds?</span>
					</td>
				</tr>

				<tr>
					<td>&nbsp;</td>
					<td>
						<input type="checkbox" id="segregatePlatform"/> 
						<span style="cursor: default"
							onclick="toggleCheckbox('segregatePlatform')">Segregate
							libraries by platform?</span>
					</td>
				</tr>

				<tr>
					<td align="right" valign="middle">Target:</td>
					<td valign="middle" width="99%">
						<input type="text" readonly="readonly" class="status"
								id="installTarget" size="80"/>
					</td>
				</tr>

				<tr>
					<td colspan="2" align="center">
						<button onclick="install()"> Install Now </button>
						&nbsp;
						<button onclick="window.close()"> Never Mind </button>
					</td>
				</tr>
			</table>
		<p>
	</body>
</html>
<
>
|
|
<
>
|
<
<
|
<

|
|
|

















<
<
<
<
|
<
<
<
<
<
<
<

<
<
<
<
<
|
<
<
<
<
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
|
<
<
<
<
|
<
<
<
<
<
<
|
<
<
<
<
<
|
<
<
<
<
<
<
<
<
<
<
<
|
<
<
<
<
<
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
|
<
<
|
<
<
<
<

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

1
2
3

4
5


6

7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27




28







29





30




31






















































































































































32




33






34





35











36





37






















































38


39




40





































































/***********************************************************************
 cmdline.h - Declares the interface to the command line parsing logic.
	It is not important for a new MySQL++ user to understand any of what

	goes on inside this module.  The examples just pass in the command 
	line arguments and magically get out the proper database server


	login parameters and the name of the database itself.


 Copyright (c) 2007 by Educational Technology Resources, Inc.
 Others may also hold copyrights on code in this file.  See the
 CREDITS.txt file in the top directory of the distribution for details.

 This file is part of MySQL++.

 MySQL++ is free software; you can redistribute it and/or modify it
 under the terms of the GNU Lesser General Public License as published
 by the Free Software Foundation; either version 2.1 of the License, or
 (at your option) any later version.

 MySQL++ is distributed in the hope that it will be useful, but WITHOUT
 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
 License for more details.

 You should have received a copy of the GNU Lesser General Public
 License along with MySQL++; if not, write to the Free Software
 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
 USA




***********************************************************************/













#if !defined(MYSQLPP_CMDLINE_H)




#define MYSQLPP_CMDLINE_H



























































































































































extern bool parse_command_line(int argc, char *argv[],






		const char** ppdb, const char** ppserver, const char** ppuser,





		const char** pppass, const char* extra_parms = "");











extern void print_usage(const char* program_name,





		const char* extra_parms = "");

























































#endif // !defined(MYSQLPP_CMDLINE_H)









































































Changes to lib/autoflag.h.

1
2
3

4
5
6
7
8
9
10
11
12
13
/// \file autoflag.h
/// \brief Defines a template for setting a flag within a given variable
/// scope, and resetting it when exiting that scope.


/***********************************************************************
 Copyright © 2007 by Educational Technology Resources, Inc.
 Others may also hold copyrights on code in this file.  See the
 CREDITS.txt file in the top directory of the distribution for details.

 This file is part of MySQL++.

 MySQL++ is free software; you can redistribute it and/or modify it
 under the terms of the GNU Lesser General Public License as published
|
|
|
>

<
|







1
2
3
4
5

6
7
8
9
10
11
12
13
/***********************************************************************
 cpool.cpp - ConnectionPool example.  Works with both Windows native
	threads and POSIX threads.  Shows how to create and use a concrete
	ConnectionPool derivative.


 Copyright (c) 2008-2010 by Educational Technology Resources, Inc.
 Others may also hold copyrights on code in this file.  See the
 CREDITS.txt file in the top directory of the distribution for details.

 This file is part of MySQL++.

 MySQL++ is free software; you can redistribute it and/or modify it
 under the terms of the GNU Lesser General Public License as published
21
22
23
24
25
26
27
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


56

57
58


59















































60
61








































































 You should have received a copy of the GNU Lesser General Public
 License along with MySQL++; if not, write to the Free Software
 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
 USA
***********************************************************************/

#if !defined(MYSQLPP_AUTOFLAG_H)

#define MYSQLPP_AUTOFLAG_H


namespace mysqlpp {

/// \brief A template for setting a flag on a variable as long as the
/// object that set it is in scope.  Flag resets when object goes
/// out of scope.  Works on anything that looks like bool.







template <class T = bool>
class AutoFlag
{
public:
	/// \brief Constructor: sets ref to true.








	AutoFlag(T& ref) :






	referent_(ref)






	{




		referent_ = true;


	}







	/// \brief Destructor: sets referent passed to ctor to false.














	~AutoFlag()

	{





		referent_ = false;






	}

private:


	T& referent_;


};


} // end namespace mysqlpp


















































#endif // !defined(MYSQLPP_AUTOFLAG_H)















































































|
>
|
>

|

<
<
<

>
>
>
>
>
>
|
|


|
>
>
>
>
>
>
>
>
|
>
>
>
>
>
>
|
>
>
>
>
>
>

>
>
>
>
|
>
>


>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>

>
>
>
>
>
|
>
>
>
>
>
>



>
>
|
>
>

>

|
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|

>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
21
22
23
24
25
26
27
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
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
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
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
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249

 You should have received a copy of the GNU Lesser General Public
 License along with MySQL++; if not, write to the Free Software
 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
 USA
***********************************************************************/

#include "cmdline.h"
#include "threads.h"

#include <iostream>

using namespace std;





#if defined(HAVE_THREADS)
// Define a concrete ConnectionPool derivative.  Takes connection
// parameters as inputs to its ctor, which it uses to create the
// connections we're called upon to make.  Note that we also declare
// a global pointer to an object of this type, which we create soon
// after startup; this should be a common usage pattern, as what use
// are multiple pools?
class SimpleConnectionPool : public mysqlpp::ConnectionPool
{
public:
	// The object's only constructor
	SimpleConnectionPool(mysqlpp::examples::CommandLine& cl) :
	conns_in_use_(0),
	db_(mysqlpp::examples::db_name),
	server_(cl.server()),
	user_(cl.user()),
	password_(cl.pass())
	{
	}

	// The destructor.  We _must_ call ConnectionPool::clear() here,
	// because our superclass can't do it for us.
	~SimpleConnectionPool()
	{
		clear();
	}

	// Do a simple form of in-use connection limiting: wait to return
	// a connection until there are a reasonably low number in use
	// already.  Can't do this in create() because we're interested in
	// connections actually in use, not those created.  Also note that
	// we keep our own count; ConnectionPool::size() isn't the same!
	mysqlpp::Connection* grab()
	{
		while (conns_in_use_ > 8) {
			cout.put('R'); cout.flush(); // indicate waiting for release
			sleep(1);
		}

		++conns_in_use_;
		return mysqlpp::ConnectionPool::grab();
	}

	// Other half of in-use conn count limit
	void release(const mysqlpp::Connection* pc)
	{
		mysqlpp::ConnectionPool::release(pc);
		--conns_in_use_;
	}

protected:
	// Superclass overrides
	mysqlpp::Connection* create()
	{
		// Create connection using the parameters we were passed upon
		// creation.  This could be something much more complex, but for
		// the purposes of the example, this suffices.
		cout.put('C'); cout.flush(); // indicate connection creation
		return new mysqlpp::Connection(
				db_.empty() ? 0 : db_.c_str(),
				server_.empty() ? 0 : server_.c_str(),
				user_.empty() ? 0 : user_.c_str(),
				password_.empty() ? "" : password_.c_str());
	}

	void destroy(mysqlpp::Connection* cp)
	{
		// Our superclass can't know how we created the Connection, so
		// it delegates destruction to us, to be safe.
		cout.put('D'); cout.flush(); // indicate connection destruction
		delete cp;
	}

	unsigned int max_idle_time()
	{
		// Set our idle time at an example-friendly 3 seconds.  A real
		// pool would return some fraction of the server's connection
		// idle timeout instead.
		return 3;
	}

private:
	// Number of connections currently in use
	unsigned int conns_in_use_;

	// Our connection parameters
	std::string db_, server_, user_, password_;
};
SimpleConnectionPool* poolptr = 0;


static thread_return_t CALLBACK_SPECIFIER
worker_thread(thread_arg_t running_flag)
{
	// Ask the underlying C API to allocate any per-thread resources it
	// needs, in case it hasn't happened already.  In this particular
	// program, it's almost guaranteed that the safe_grab() call below
	// will create a new connection the first time through, and thus
	// allocate these resources implicitly, but there's a nonzero chance
	// that this won't happen.  Anyway, this is an example program,
	// meant to show good style, so we take the high road and ensure the
	// resources are allocated before we do any queries.
	mysqlpp::Connection::thread_start();
	cout.put('S'); cout.flush(); // indicate thread started

	// Pull data from the sample table a bunch of times, releasing the
	// connection we use each time.
	for (size_t i = 0; i < 6; ++i) {
		// Go get a free connection from the pool, or create a new one
		// if there are no free conns yet.  Uses safe_grab() to get a
		// connection from the pool that will be automatically returned
		// to the pool when this loop iteration finishes.
		mysqlpp::ScopedConnection cp(*poolptr, true);
		if (!cp) {
			cerr << "Failed to get a connection from the pool!" << endl;
			break;
		}

		// Pull a copy of the sample stock table and print a dot for
		// each row in the result set.
		mysqlpp::Query query(cp->query("select * from stock"));
		mysqlpp::StoreQueryResult res = query.store();
		for (size_t j = 0; j < res.num_rows(); ++j) {
			cout.put('.');
		}

		// Delay 1-4 seconds before doing it again.  Because this can
		// delay longer than the idle timeout, we'll occasionally force
		// the creation of a new connection on the next loop.
		sleep(rand() % 4 + 1);	
	}

	// Tell main() that this thread is no longer running
	*reinterpret_cast<bool*>(running_flag) = false;
	cout.put('E'); cout.flush(); // indicate thread ended
	
	// Release the per-thread resources before we exit
	mysqlpp::Connection::thread_end();

	return 0;
}
#endif


int
main(int argc, char *argv[])
{
#if defined(HAVE_THREADS)
	// Get database access parameters from command line
	mysqlpp::examples::CommandLine cmdline(argc, argv);
	if (!cmdline) {
		return 1;
	}

	// Create the pool and grab a connection.  We do it partly to test
	// that the parameters are good before we start doing real work, and
	// partly because we need a Connection object to call thread_aware()
	// on to check that it's okay to start doing that real work.  This
	// latter check should never fail on Windows, but will fail on most
	// other systems unless you take positive steps to build with thread
	// awareness turned on.  See README-*.txt for your platform.
	poolptr = new SimpleConnectionPool(cmdline);
	try {
		mysqlpp::ScopedConnection cp(*poolptr, true);
		if (!cp->thread_aware()) {
			cerr << "MySQL++ wasn't built with thread awareness!  " <<
					argv[0] << " can't run without it." << endl;
			return 1;
		}
	}
	catch (mysqlpp::Exception& e) {
		cerr << "Failed to set up initial pooled connection: " <<
				e.what() << endl;
		return 1;
	}

	// Setup complete.  Now let's spin some threads...
	cout << endl << "Pool created and working correctly.  Now to do "
			"some real work..." << endl;
	srand((unsigned int)time(0));
	bool running[] = {
			true, true, true, true, true, true, true,
			true, true, true, true, true, true, true };
	const size_t num_threads = sizeof(running) / sizeof(running[0]);
	size_t i;
	for (i = 0; i < num_threads; ++i) {
		if (int err = create_thread(worker_thread, running + i)) {
			cerr << "Failed to create thread " << i <<
					": error code " << err << endl;
			return 1;
		}
	}

	// Test the 'running' flags every second until we find that they're
	// all turned off, indicating that all threads are stopped.
	cout.put('W'); cout.flush(); // indicate waiting for completion
	do {
		sleep(1);
		i = 0;
		while (i < num_threads && !running[i]) ++i;
	}
	while (i < num_threads);
	cout << endl << "All threads stopped!" << endl;

	// Shut it all down...
	delete poolptr;
	cout << endl;
#else
	(void)argc;		// warning squisher
	cout << argv[0] << " requires that threads be enabled!" << endl;
#endif

	return 0;
}

Changes to lib/cmdline.h.




1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
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





56








57








58




59

60




61




62



63






64

























65

66
67
68


69
70
71
72
73
74
75

76
77




78
79
80
81
82
83















84
85
86
87
88



89
90

91






92
93

94








95





















96
97




98


99
100
101


102
103






104
105
106
107




108

109
110


111

112
113


114

115


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
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
191

192

193
194
195



196
197








198




199
200

201
202
203


204







205






206




207






208

209
210
211
212






213









214
215

216
217
218










219
220
221











222










223
224









225



































226













227


228


229


230
231

232
233
234
235


236
237

238
239
240
241



/***********************************************************************
 cmdline.h - Declares the interface to the MySQL++'s command line
	parsing logic, used by the examples and the utility programs.
	Not intended for use by third parties!	If it breaks, you
	get to keep all the pieces.

 Copyright (c) 2007-2009 by Educational Technology Resources, Inc.
 Others may also hold copyrights on code in this file.  See the
 CREDITS.txt file in the top directory of the distribution for details.

 This file is part of MySQL++.

 MySQL++ is free software; you can redistribute it and/or modify it
 under the terms of the GNU Lesser General Public License as published
 by the Free Software Foundation; either version 2.1 of the License, or
 (at your option) any later version.

 MySQL++ is distributed in the hope that it will be useful, but WITHOUT
 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
 License for more details.

 You should have received a copy of the GNU Lesser General Public
 License along with MySQL++; if not, write to the Free Software
 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
 USA
***********************************************************************/

#if !defined(MYSQLPP_CMDLINE_H)
#define MYSQLPP_CMDLINE_H

#include "common.h"

#include <string>

#include <vector>

#include <assert.h>

namespace mysqlpp {
	/// \brief Parses command line arguments and holds the results.


	///
	/// This class just contains common functionality and data











	/// structures; instantiable subclasses follow.
	class MYSQLPP_EXPORT CommandLineBase
	{
	public:







		//// Public types
		/// \brief Type for a list of arguments

		typedef std::vector<std::string> ArgumentList;
		/// \brief Iterator into ArgumentList
		typedef ArgumentList::const_iterator ArgumentListIt;









		//// Public interface








		/// \brief Get reference to list of command line arguments past








		/// the last flag and its possible argument.





		const ArgumentList& extra_args() const 








				{ return extra_args_; }













		/// \brief Return truthy value if command line was parsed

		/// successfully




		operator void*() const




		{



			return successful_ ? const_cast<bool*>(&successful_) : 0;






		}



























	protected:
		//// Subclass interface
		/// \brief Hidden ctor to prevent instantiation


		CommandLineBase(int argc, char* const argv[], const char* opts) :
		argc_(argc),
		argv_(argv),
		opts_(opts),
		successful_(argc > 0 && argv && opts)
		{
			assert(successful_);

		}
		/// \brief Hidden dtor to prevent instantiation




		virtual ~CommandLineBase() { }

		/// \brief If object is still marked as "successful", save
		/// non-option arguments to extra_args_ list.  Subclass ctor
		/// should call this after the parse_next() loop gets EOF.
		void finish_parse();
















		/// \brief Accessor for getopt()'s optarg global
		const char* option_argument() const;
		/// \brief Accessor for getopt()'s optind global
		int option_index() const;




		/// \brief Called by a subclass when encountering a command

		/// line parsing error.






		///
		/// Prints the passed message, calls subclass's print_usage(),

		/// and marks the object as no longer successful.








		void parse_error(const char* message = 0);






















		/// \brief Wrapper for getopt()




		int parse_next() const;



		/// \brief Show a message explaining the program's proper usage
		virtual void print_usage() const = 0;



		/// \brief Get the file name of the program's executable






		const char* program_name() const { return argv_[0]; }

		/// \brief Returns true if nothing has gone wrong since calling
		/// the ctor.




		bool successful() const { return successful_; }


	private:


		//// Internal data

		int argc_;
		char* const* argv_;


		const char* opts_;

		bool successful_;


		ArgumentList extra_args_;









	};




















	/// \brief Stuff related to MySQL++ examples specifically
	namespace examples {
		/// \brief Name of examples' DB





		extern MYSQLPP_EXPORT const char* db_name;

		/// \brief Command line parsing mechanism for ../examples/*.cpp



		class MYSQLPP_EXPORT CommandLine : public CommandLineBase
		{



		public:
			//// Public interface
			/// \brief Constructor
			CommandLine(int argc, char* const argv[],
					const char* user = 0, const char* pass = 0,












					const char* usage_extra = 0);















			/// \brief Show a message explaining the program's proper usage

			///

			/// Calls print_usage(const char*), passing along the

			/// "usage_extra" parameter passed to the ctor
			void print_usage() const { print_usage(usage_extra_); }



			/// \brief Show a message explaining the program's proper
			/// usage, with custom extra info after standard command
			/// line usage bits.
			void print_usage(const char* extra) const;


			/// \brief Return true if we're in "dtest" mode

			/// This happens when an example gets the -D flag, always
			/// passed by the dtest script to ask the programs it runs
			/// to suppress any nondeterministic output.

			bool dtest_mode() const { return dtest_mode_; }



			/// \brief Return the DB password (-p argument)

			const char* pass() const { return pass_; }


			/// \brief Return the -m flag value





			///


			/// This flag is currently only used by examples/deadlock,













			/// but it's really a nonspecific "mode" value, which could

			/// be used by other examples in the future.




			int run_mode() const { return run_mode_; }

			/// \brief Return the DB server name (-s argument)



			const char* server() const { return server_; }


			/// \brief Return the DB user name (-u argument)

			const char* user() const { return user_; }















		private:


			//// Internal data
			// Examples-specific command line parse results
			bool dtest_mode_;

			int run_mode_;

			const char* server_;


			const char* user_;



			const char* pass_;
			const char* usage_extra_;
		};

	} // end namespace mysqlpp::examples











	/// \brief Stuff specific to the ssqlsxlat tool
	namespace ssqlsxlat {
		/// \brief Command line parser for MySQL++'s ssqlsxlat tool
		class MYSQLPP_EXPORT CommandLine : public CommandLineBase




		{
		public:


			//// Public types
			/// \brief Types of inputs that ssqlsxlat will accept





			enum SourceSink {
				ss_unknown,	///< no known input type given yet
				ss_ssqls1,	///< a C++ file containing an SSQLS v1 declaration

				ss_ssqls2,	///< an SSQLS v2 file

				ss_table	///< an existing DB table schema
			};




			//// Public interface
			/// \brief Constructor








			CommandLine(int argc, char* const argv[]);





			/// \brief Show a message explaining the program's proper usage

			void print_usage() const;

			/// \brief Return the name of the input source


			///







			/// This can be a file name, a table name, etc.  Call






			/// input_source() to determine the proper interpretation.




			const char* input() const { return input_; }








			/// \brief The input source type
			SourceSink input_source() const { return input_source_; }

			/// \brief The output sink (destination) type






			SourceSink output_sink() const { return output_sink_; }










			/// \brief The base name of the output file

			const char* output() const { return output_; }

			/// \brief DB password, when input type is is_table










			const char* pass() const { return pass_; }

			/// \brief DB server name, when input type is is_table











			const char* server() const { return server_; }











			/// \brief DB user name, when input type is is_table









			const char* user() const { return user_; }

















































		private:


			//// Internal data: command line parse results


			const char* input_;


			const char* output_;
			const char* pass_;

			const char* server_;
			const char* user_;
			SourceSink input_source_;
			SourceSink output_sink_;


		};
	} // end namespace mysqlpp::ssqlsxlat

} // end namespace mysqlpp

#endif // !defined(MYSQLPP_CMDLINE_H)

>
>
>

<
<
<
<
|
|
|
|



















|
|



|
>
|

|


|
>
>
|
|
>
>
>
>
>
>
>
>
>
>
>
|
|
|
|
>
>
>
>
>
>
>
|
|
>
|
|
<
>
>
>
>
>
>

>
>
|
>
>
>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
|
>
>
>
>
>
|
>
>
>
>
>
>
>
>
|
>
>
>
>
>
>
>
>

>
>
>
>
|
>
|
>
>
>
>
|
>
>
>
>
|
>
>
>
|
>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

>
|
|
<
>
>
|
<
<
<
<
|
<
>
|
|
>
>
>
>
|

|
|
|
<
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
<
<
<
<
>
>
>
|
|
>
|
>
>
>
>
>
>
|
<
>
|
>
>
>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

|
>
>
>
>
|
>
>
|
<
<
>
>
|
|
>
>
>
>
>
>
|

|
|
>
>
>
>
|
>
|
|
>
>
|
>
|
<
>
>
|
>
|
>
>
|
>
>
>
>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
>
>
>
|
|
<
|
>
>
>
>
>
|
|
|
>
>
>
|
|
>
>
>
|
<
|
|
|
>
>
>
>
>
>
>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
|
>
>
>
|
>
|
>
|
>
|
<
>
>
|
<
<
|
<
>
|
|
>
|
<
|
>
|
|
>
>
|
>
|
>
|
|
>
>
>
>
>
|
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
|
>
>
>
>
|
|
|
>
>
>
|
|
>
|
>
|
>
>
>
>
>
>
>
>
>
>
>
|
>
>
>
|
>
>
|
<
<
>
|
>
|
>
>
|
>
>
>
|
|
<
>
|
>
>
>
>
>
>
>
|
>
>
|
|
<
|
<
>
>
>
>
|
|
>
>
|
|
>
>
>
>
>
|
<
<
>
|
>
|
<
|
>
>
>
|
|
>
>
>
>
>
>
>
>
|
>
>
>
>
|
|
>
|
|
|
>
>
|
>
>
>
>
>
>
>
|
>
>
>
>
>
>
|
>
>
>
>
|
>
>
>
>
>
>
|
>
|
|
|
|
>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
|
<
>
|
|
|
>
>
>
>
>
>
>
>
>
>
|
|
|
>
>
>
>
>
>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
|
|
>
>
>
>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
>
|
>
>
|
>
>
|
|
>
|
|
<
<
>
>
|
|
>


|

1
2
3
4




5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
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
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71

72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
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
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
191
192
193
194
195
196

197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212




213
214
215
216
217
218
219
220
221
222
223
224
225
226

227
228
229
230
231
232
233
234
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


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
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
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
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390

391
392
393


394

395
396
397
398
399

400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471


472
473
474
475
476
477
478
479
480
481
482
483

484
485
486
487
488
489
490
491
492
493
494
495
496
497

498

499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514


515
516
517
518

519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595

596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709


710
711
712
713
714
715
716
717
718
/// \file dbdriver.h
/// \brief Declares the DBDriver class.

/***********************************************************************




 Copyright (c) 1998 by Kevin Atkinson, (c) 1999-2001 by MySQL AB, and
 (c) 2004-2009 by Educational Technology Resources, Inc.  Others may
 also hold copyrights on code in this file.  See the CREDITS.txt file
 in the top directory of the distribution for details.

 This file is part of MySQL++.

 MySQL++ is free software; you can redistribute it and/or modify it
 under the terms of the GNU Lesser General Public License as published
 by the Free Software Foundation; either version 2.1 of the License, or
 (at your option) any later version.

 MySQL++ is distributed in the hope that it will be useful, but WITHOUT
 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
 License for more details.

 You should have received a copy of the GNU Lesser General Public
 License along with MySQL++; if not, write to the Free Software
 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
 USA
***********************************************************************/

#if !defined(MYSQLPP_DBDRIVER_H)
#define MYSQLPP_DBDRIVER_H

#include "common.h"

#include "options.h"

#include <typeinfo>

#include <limits.h>

namespace mysqlpp {

/// \brief Provides a thin abstraction layer over the underlying database 
/// client library.
///
/// This class does as little as possible to adapt between its public
/// interface and the interface required by the underlying C API.  That
/// is, in fact, its only mission.  The high-level interfaces indended
/// for use by MySQL++ users are in Connection, Query, Result, and
/// ResUse, all of which delegate the actual database communication to
/// an object of this type, created by Connection.  If you really need
/// access to the low-level database driver, get it via
/// Connection::driver(); don't create DBDriver objects directly.
///
/// Currently this is a concrete class for wrapping the MySQL C API.
/// In the future, it may be turned into an abstract base class, with
/// subclasses for different database server types.

class MYSQLPP_EXPORT DBDriver
{
public:
	/// \brief Result code returned by next_result()
	enum nr_code {
		nr_more_results,	///< success, with more results to come
		nr_last_result,		///< success, last result received
		nr_error,			///< problem retrieving next result
		nr_not_supported	///< this C API doesn't support "next result"
	};

	/// \brief Create object
	DBDriver();

	/// \brief Duplicate an existing driver

	///
	/// \param other existing DBDriver object
	///
	/// This establishes a new database server connection with the same
	/// parameters as the other driver's.
	DBDriver(const DBDriver& other);

	/// \brief Destroy object
	virtual ~DBDriver();

	/// \brief Return the number of rows affected by the last query
	///
	/// Wraps \c mysql_affected_rows() in the MySQL C API.
	ulonglong affected_rows()
	{
		error_message_.clear();
		return mysql_affected_rows(&mysql_);
	}

	/// \brief Get database client library version
	///
	/// Wraps \c mysql_get_client_info() in the MySQL C API.
	std::string client_version() const
	{
		error_message_.clear();
		return mysql_get_client_info();
	}

	/// \brief Establish a new connection using the same parameters as
	/// an existing connection.
	///
	/// \param mysql existing MySQL C API connection object
	bool connect(const MYSQL& mysql);

	/// \brief Connect to database server
	///
	/// If you call this method on an object that is already connected
	/// to a database server, the previous connection is dropped and a
	/// new connection is established.
	virtual bool connect(const char* host, const char* socket_name,
			unsigned int port, const char* db, const char* user,
			const char* password);

	/// \brief Return true if we have an active connection to the
	/// database server.
	///
	/// This does not actually check whether the connection is viable,
	/// it just indicates whether there was previously a successful
	/// connect() call and no disconnect().  Call ping() to actually
	/// test the connection's viability.
	bool connected() const { return is_connected_; }

	/// \brief Establish a new connection as a copy of an existing one
	///
	/// \param other the connection to copy
	void copy(const DBDriver& other);

	/// \brief Ask the database server to create a database
	///
	/// \param db name of database to create
	///
	/// \return true if database was created successfully
	bool create_db(const char* db) const;

	/// \brief Seeks to a particualr row within the result set
	///
	/// Wraps mysql_data_seek() in MySQL C API.
	void data_seek(MYSQL_RES* res, ulonglong offset) const
	{
		error_message_.clear();
		mysql_data_seek(res, offset);
	}

	/// \brief Drop the connection to the database server
	///
	/// This method should only be used by MySQL++ library internals.
	/// Unless you use the default constructor, this object should
	/// always be connected.
	void disconnect();

	/// \brief Drop a database
	///
	/// \param db name of database to destroy
	///
	/// \return true if database was created successfully
	bool drop_db(const std::string& db) const;

	/// \brief Enable SSL-encrypted connection.
	///
	/// \param key the pathname to the key file
	/// \param cert the pathname to the certificate file
	/// \param ca the pathname to the certificate authority file
	/// \param capath directory that contains trusted SSL CA
	///        certificates in pem format.
	/// \param cipher list of allowable ciphers to use
	///
	/// \return False if call fails or the C API library wasn't compiled
	/// with SSL support enabled.
	///
	/// Must be called before connection is established.
	///
	/// Wraps \c mysql_ssl_set() in MySQL C API.
	bool enable_ssl(const char* key = 0, const char* cert = 0,
			const char* ca = 0, const char* capath = 0,
			const char* cipher = 0);

	/// \brief Return error message for last MySQL error associated with
	/// this connection.
	///

	/// Can return a MySQL++ DBDriver-specific error message if there
	/// is one.  If not, it simply wraps \c mysql_error() in the MySQL C API.
	const char* error()




	{

		return error_message_.length() ? error_message_.c_str() : mysql_error(&mysql_);
	}

	/// \brief Return last MySQL error number associated with this
	/// connection
	///
	/// Wraps \c mysql_errno() in the MySQL C API.
	int errnum() { return mysql_errno(&mysql_); }

	/// \brief Return a SQL-escaped version of the given character
	/// buffer
	///

	/// \param to character buffer to hold escaped version; must
	/// point to at least (length * 2 + 1) bytes
	/// \param from pointer to the character buffer to escape
	/// \param length number of characters to escape
	///
	/// \retval number of characters placed in escaped
	///
	/// Wraps \c mysql_real_escape_string() in the MySQL C API.
	///
	/// Proper SQL escaping takes the database's current character set 
	/// into account, however if a database connection isn't available
	/// DBDriver also provides a static version of this same method.
	///
	/// \sa escape_string_no_conn(char*, const char*, size_t)
	size_t escape_string(char* to, const char* from, size_t length)
	{




		error_message_.clear();
		return mysql_real_escape_string(&mysql_, to, from, 
				static_cast<unsigned long>(length));
	}

	/// \brief Return a SQL-escaped version of a character buffer
	///
	/// \param ps pointer to C++ string to hold escaped version; if
	/// original is 0, also holds the original data to be escaped
	/// \param original if given, pointer to the character buffer to
	/// escape instead of contents of *ps
	/// \param length if both this and original are given, number of
	/// characters to escape instead of ps->length()
	///

	/// \retval number of characters placed in *ps
	///
	/// This method has three basic operation modes:
	///
	/// - Pass just a pointer to a C++ string containing the original
	///   data to escape, plus act as receptacle for escaped version
	/// - Pass a pointer to a C++ string to receive escaped string plus
	///   a pointer to a C string to be escaped
	/// - Pass nonzero for all parameters, taking original to be a
	///   pointer to an array of char with given length; does not treat
	///   null characters as special
	///
	/// There's a degenerate fourth mode, where ps is zero: simply
	/// returns 0, because there is nowhere to store the result.
	///
	/// Note that if original is 0, we always ignore the length
	/// parameter even if it is nonzero.  Length always comes from
	/// ps->length() in this case.
	///
	/// ps is a pointer because if it were a reference, the other
	/// overload would be impossible to call: the compiler would
	/// complain that the two overloads are ambiguous because
	/// std::string has a char* conversion ctor. A nice bonus is that
	/// pointer syntax makes it clearer that the first parameter is an
	/// "out" parameter.
	///
	/// \see comments for escape_string(char*, const char*, size_t)
	/// for further details.
	/// 
	/// \sa escape_string_no_conn(std::string*, const char*, size_t)
	size_t escape_string(std::string* ps, const char* original,
			size_t length);

	/// \brief SQL-escapes the given string without reference to the 
	/// character set of a database server.
	///
	/// Wraps \c mysql_escape_string() in the MySQL C API.
	///
	/// \sa escape_string(char*, const char*, size_t)
	static size_t escape_string_no_conn(char* to, const char* from,
			size_t length)
	{


		return mysql_escape_string(to, from,
				static_cast<unsigned long>(length));
	}

	/// \brief SQL-escapes the given string without reference to the 
	/// character set of a database server.
	///
	/// \sa escape_string(std::string*, const char*, size_t),
	/// escape_string_no_conn(char*, const char*, size_t)
	static size_t escape_string_no_conn(std::string* ps, 
			const char* original = 0, size_t length = 0);

	/// \brief Executes the given query string
	///
	/// Wraps \c mysql_real_query() in the MySQL C API.
	bool execute(const char* qstr, size_t length)
	{
		error_message_.clear();
		return !mysql_real_query(&mysql_, qstr,
				static_cast<unsigned long>(length));
	}

	/// \brief Returns the next raw C API row structure from the given
	/// result set.
	///
	/// This is for "use" query result sets only.  "store" queries have
	/// all the rows already.

	///
	/// Wraps \c mysql_fetch_row() in MySQL C API.
	MYSQL_ROW fetch_row(MYSQL_RES* res) const
	{
		error_message_.clear();
		return mysql_fetch_row(res);
	}

	/// \brief Returns the lengths of the fields in the current row
	/// from a "use" query.
	///
	/// Wraps \c mysql_fetch_lengths() in MySQL C API.
	const unsigned long* fetch_lengths(MYSQL_RES* res) const
	{
		error_message_.clear();
		return mysql_fetch_lengths(res);
	}

	/// \brief Returns information about a particular field in a result
	/// set
	///
	/// \param res result set to fetch field information for
	/// \param i field number to fetch information for, if given
	///
	/// If i parameter is given, this call is like a combination of
	/// field_seek() followed by fetch_field() without the i parameter,
	/// which otherwise just iterates through the set of fields in the
	/// given result set.
	///
	/// Wraps \c mysql_fetch_field() and mysql_fetch_field_direct() in
	/// MySQL C API.  (Which one it uses depends on i parameter.)
	MYSQL_FIELD* fetch_field(MYSQL_RES* res, size_t i = UINT_MAX) const
	{
		error_message_.clear();
		return i == UINT_MAX ? mysql_fetch_field(res) :
				mysql_fetch_field_direct(res,
				static_cast<unsigned int>(i));
	}


	/// \brief Jumps to the given field within the result set
	///
	/// Wraps \c mysql_field_seek() in MySQL C API.
	void field_seek(MYSQL_RES* res, size_t field) const
	{
		error_message_.clear();
		mysql_field_seek(res, MYSQL_FIELD_OFFSET(field));
	}

	/// \brief Releases memory used by a result set
	///
	/// Wraps \c mysql_free_result() in MySQL C API.
	void free_result(MYSQL_RES* res) const
	{
		error_message_.clear();
		mysql_free_result(res);
	}


	/// \brief Return the connection options object
	st_mysql_options get_options() const { return mysql_.options; }

	/// \brief Get information about the IPC connection to the
	/// database server
	///
	/// String contains info about type of connection (e.g. TCP/IP,
	/// named pipe, Unix socket...) and the server hostname.
	///
	/// Wraps \c mysql_get_host_info() in the MySQL C API.
	std::string ipc_info()
	{
		error_message_.clear();
		return mysql_get_host_info(&mysql_);
	}

	/// \brief Get ID generated for an AUTO_INCREMENT column in the
	/// previous INSERT query.
	///
	/// \retval 0 if the previous query did not generate an ID.  Use
	/// the SQL function LAST_INSERT_ID() if you need the last ID
	/// generated by any query, not just the previous one.  This
	/// applies to stored procedure calls because this function returns
	/// the ID generated by the last query, which was a CALL statement,
	/// and CALL doesn't generate IDs.  You need to use LAST_INSERT_ID()
	/// to get the ID in this case.
	ulonglong insert_id()
	{
		error_message_.clear();
		return mysql_insert_id(&mysql_);
	}

	/// \brief Kill a MySQL server thread
	///
	/// \param tid ID of thread to kill
	///
	/// Wraps \c mysql_kill() in the MySQL C API.
	///

	/// \see thread_id()
	bool kill(unsigned long tid)
	{


		error_message_.clear();

		return !mysql_kill(&mysql_, tid);
	}

	/// \brief Returns true if there are unconsumed results from the
	/// most recent query.

	///
	/// Wraps \c mysql_more_results() in the MySQL C API.
	bool more_results()
	{
		error_message_.clear();
		#if MYSQL_VERSION_ID > 41000		// only in MySQL v4.1 +
			return mysql_more_results(&mysql_);
		#else
			return false;
		#endif
	}

	/// \brief Moves to the next result set from a multi-query
	///
	/// \return A code indicating whether we successfully found another
	/// result, there were no more results (but still success) or
	/// encountered an error trying to find the next result set.
	///
	/// Wraps \c mysql_next_result() in the MySQL C API, with
	/// translation of its return value from magic integers to nr_code
	/// enum values.
	nr_code next_result()
	{
		error_message_.clear();
		#if MYSQL_VERSION_ID > 41000		// only in MySQL v4.1 +
			switch (mysql_next_result(&mysql_)) {
				case 0:  return nr_more_results;
				case -1: return nr_last_result;
				default: return nr_error;
			}
		#else
			return nr_not_supported;
		#endif
	}

	/// \brief Returns the number of fields in the given result set
	///
	/// Wraps \c mysql_num_fields() in MySQL C API.
	int num_fields(MYSQL_RES* res) const
	{
		error_message_.clear();
		return mysql_num_fields(res);
	}

	/// \brief Returns the number of rows in the given result set
	///
	/// Wraps \c mysql_num_rows() in MySQL C API.
	ulonglong num_rows(MYSQL_RES* res) const
	{
		error_message_.clear();
		return mysql_num_rows(res);
	}

	/// \brief "Pings" the MySQL database
	///
	/// This function will try to reconnect to the server if the 
	/// connection has been dropped.  Wraps \c mysql_ping() in the MySQL C API.
	/// 
	/// \retval true if server is responding, regardless of whether we had
	/// to reconnect or not
	/// \retval false if either we already know the connection is down
	/// and cannot re-establish it, or if the server did not respond to
	/// the ping and we could not re-establish the connection.
	bool ping()
	{
		error_message_.clear();
		return !mysql_ping(&mysql_);
	}

	/// \brief Returns version number of MySQL protocol this connection
	/// is using
	///


	/// Wraps \c mysql_get_proto_info() in the MySQL C API.
	int protocol_version()
	{
		error_message_.clear();
		return mysql_get_proto_info(&mysql_);
	}

	/// \brief Returns information about the last executed query
	///
	/// Wraps \c mysql_info() in the MySQL C API
	std::string query_info();


	/// \brief Asks the database server to refresh certain internal data
	/// structures.
	///
	/// Wraps \c mysql_refresh() in the MySQL C API.  There is no
	/// corresponding interface for this in higher level MySQL++ classes
	/// because it was undocumented until recently, and it's a pretty
	/// low-level thing.  It's designed for things like MySQL
	/// Administrator.
	bool refresh(unsigned options)
	{
		error_message_.clear();
		return !mysql_refresh(&mysql_, options);
	}


	/// \brief Returns true if the most recent result set was empty

	///
	/// Wraps \c mysql_field_count() in the MySQL C API, returning true
	/// if it returns 0.
	bool result_empty()
	{
		error_message_.clear();
		return mysql_field_count(&mysql_) == 0;
	}

	/// \brief Asks the database server to switch to a different database
	bool select_db(const char* db)
	{
		error_message_.clear();
		return !mysql_select_db(&mysql_, db);
	}



	/// \brief Get the database server's version number
	///
	/// Wraps \c mysql_get_server_info() in the MySQL C API.
	std::string server_version()

	{
		error_message_.clear();
		return mysql_get_server_info(&mysql_);
	}

	/// \brief Sets a connection option
	///
	/// This is the database-independent high-level option setting
	/// interface that Connection::set_option() calls.  There are
	/// several private overloads that actually implement the option
	/// setting.
	///
	/// \see Connection::set_option(Option*) for commentary
	bool set_option(Option* o);

	/// \brief Set MySQL C API connection option
	///
	/// \internal Wraps \c mysql_options() in C API.
	bool set_option(mysql_option moption, const void* arg = 0)
	{
		error_message_.clear();
		return !mysql_options(&mysql_, moption,
				static_cast<const char*>(arg));
	}

	#if MYSQL_VERSION_ID >= 40101
	/// \brief Set MySQL C API connection option
	///
	/// \internal Wraps \c mysql_set_server_option() in C API.
	bool set_option(enum_mysql_set_option msoption)
	{
		error_message_.clear();
		return !mysql_set_server_option(&mysql_, msoption);
	}
	#endif

	/// \brief Set MySQL C API connection option
	///
	/// Manipulates the MYSQL.client_flag bit mask.  This allows these
	/// flags to be treated the same way as any other connection option,
	/// even though the C API handles them differently.
	bool set_option(unsigned int option, bool arg);

	/// \brief Same as set_option(), except that it won't override
	/// a previously-set option.
	bool set_option_default(Option* o)
	{
		const std::type_info& ti = typeid(o);
		for (OptionList::const_iterator it = applied_options_.begin();
				it != applied_options_.end();
				++it) {
			if (typeid(*it) == ti) {
				delete o;
				return "";		// option of this type already set
			}
		}

		return set_option(o);
	}

	/// \brief Ask database server to shut down.
	///
	/// User must have the "shutdown" privilege.
	///
	/// Wraps \c mysql_shutdown() in the MySQL C API.
	bool shutdown();

	/// \brief Returns the database server's status
	///
	/// String is similar to that returned by the \c mysqladmin
	/// \c status command.  Among other things, it contains uptime 
	/// in seconds, and the number of running threads, questions
	/// and open tables.
	///
	/// Wraps \c mysql_stat() in the MySQL C API.
	std::string server_status()
	{

		error_message_.clear();
		return mysql_stat(&mysql_);
	}

	/// \brief Saves the results of the query just execute()d in memory
	/// and returns a pointer to the MySQL C API data structure the
	/// results are stored in.
	///
	/// \sa use_result()
	///
	/// Wraps \c mysql_store_result() in the MySQL C API.
	MYSQL_RES* store_result()
	{
		error_message_.clear();
		return mysql_store_result(&mysql_);
	}

	/// \brief Returns true if MySQL++ and the underlying MySQL C API
	/// library were both compiled with thread awareness.
	///
	/// This is based in part on a MySQL C API function
	/// mysql_thread_safe().  We deliberately don't call this wrapper
	/// thread_safe() because it's a misleading name: linking to
	/// thread-aware versions of the MySQL++ and C API libraries doesn't
	/// automatically make your program "thread-safe".  See the
	/// <a href="../userman/threads.html">chapter on threads</a> in the
	/// user manual for more information and guidance.
	static bool thread_aware();

	/// \brief Tells the underlying MySQL C API library that this thread
	/// is done using the library.
	///
	/// This exists because the MySQL C API library allocates some per-thread
	/// memory which it doesn't release until you call this.
	static void thread_end()
	{
		#if MYSQL_VERSION_ID > 40000		// only in MySQL v4.0 +
			mysql_thread_end();
		#endif
	}

	/// \brief Returns the MySQL server thread ID for this connection
	///
	/// This has nothing to do with threading on the client side. It's
	/// a server-side thread ID, to be used with kill().
	unsigned long thread_id()
	{
		error_message_.clear();
		return mysql_thread_id(&mysql_);
	}

	/// \brief Tells the underlying C API library that the current
	/// thread will be using the library's services.
	///
	/// \retval True if there was no problem
	///
	/// The MySQL++ user manual's <a href="../userman/threads.html">chapter
	/// on threads</a> details two major strategies for dealing with
	/// connections in the face of threads.  If you take the simpler
	/// path, creating one DBDriver object per thread, it is never
	/// necessary to call this function; the underlying C API will call it
	/// for you when you establish the first database server connection
	/// from that thread.  If you use a more complex connection
	/// management strategy where it's possible for one thread to
	/// establish a connection that another thread uses, you must call
	/// this from each thread that can use the database before it creates
	/// any MySQL++ objects.  If you use a DBDriverPool object, this
	/// applies; DBDriverPool isn't smart enough to call this for you,
	/// and the MySQL C API won't do it, either.
	static bool thread_start()
	{
		#if MYSQL_VERSION_ID > 40000		// only in MySQL v4.0 +
			return !mysql_thread_init();
		#else
			return false;
		#endif
	}

	/// \brief Returns a result set from the last-executed query which
	/// we can walk through in linear fashion, which doesn't store all
	/// result sets in memory.
	///
	/// \sa store_result
	///
	/// Wraps \c mysql_use_result() in the MySQL C API.
	MYSQL_RES* use_result()
	{
		error_message_.clear();
		return mysql_use_result(&mysql_);
	}

protected:
	/// \brief Does things common to both connect() overloads, before
	/// each go and establish the connection in their different ways.
	bool connect_prepare();

	/// \brief Common implementation of set_option(Option*) and the
	/// delayed option setting code in connect_prepare()
	bool set_option_impl(Option* o);

private:
	/// \brief Data type of the list of applied connection options
	typedef std::deque<Option*> OptionList;

	/// \brief Iterator into an OptionList
	typedef OptionList::iterator OptionListIt;

	/// \brief Hidden assignment operator; we don't want to be copied
	/// that way.  What would it mean?
	DBDriver& operator=(const DBDriver&);

	MYSQL mysql_;
	bool is_connected_;
	OptionList applied_options_;


	OptionList pending_options_;
	mutable std::string error_message_;
};


} // end namespace mysqlpp

#endif // !defined(MYSQLPP_DBDRIVER_H)

Changes to lib/comparable.h.

1
2
3
4
5
6
7
8
9
10
11
12
13
/// \file comparable.h
/// \brief Declares the Comparable<T> mixin

/***********************************************************************
 Copyright (c) 1998 by Kevin Atkinson, (c) 1999-2001 by MySQL AB, and
 (c) 2004-2008 by Educational Technology Resources, Inc.  Others may
 also hold copyrights on code in this file.  See the CREDITS.txt file
 in the top directory of the distribution for details.

 This file is part of MySQL++.

 MySQL++ is free software; you can redistribute it and/or modify it
 under the terms of the GNU Lesser General Public License as published
|
|



|







1
2
3
4
5
6
7
8
9
10
11
12
13
/// \file dbdriver.h
/// \brief Declares the DBDriver class.

/***********************************************************************
 Copyright (c) 1998 by Kevin Atkinson, (c) 1999-2001 by MySQL AB, and
 (c) 2004-2009 by Educational Technology Resources, Inc.  Others may
 also hold copyrights on code in this file.  See the CREDITS.txt file
 in the top directory of the distribution for details.

 This file is part of MySQL++.

 MySQL++ is free software; you can redistribute it and/or modify it
 under the terms of the GNU Lesser General Public License as published
21
22
23
24
25
26
27
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












56







57









58











59













































































60



61












62





63




64

65


























































































































66









67










68






69













70

71






























72




73










74






75






































76














77
78
79
80
81
82
83
84
85

86



87


88
89
90

91
92
93





94
95
96

97
98


 You should have received a copy of the GNU Lesser General Public
 License along with MySQL++; if not, write to the Free Software
 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
 USA
***********************************************************************/

#if !defined(MYSQLPP_COMPARABLE_H)
#define MYSQLPP_COMPARABLE_H









namespace mysqlpp {

/// \brief Mix-in that gives its subclass a full set of comparison

/// operators.








///
/// Simply by inheriting publically from this and implementing


/// compare(), the subclass gains a full set of comparison operators,
/// because all of the operators are implemented in terms of compare().
template <class T>
class Comparable
{
public:







	/// \brief Returns true if "other" is equal to this object


	bool operator ==(const T& other) const







	{


		return !compare(other);







	}






















































	/// \brief Returns true if "other" is not equal to this object






	bool operator !=(const T& other) const






	{


















		return compare(other);






































	}










































	/// \brief Returns true if "other" is less than this object












	bool operator <(const T& other) const







	{









		return compare(other) < 0;











	}

















































































	/// \brief Returns true if "other" is less than or equal to this object












	bool operator <=(const T& other) const





	{




		return compare(other) <= 0;

	}




































































































































	/// \brief Returns true if "other" is greater than this object










	bool operator >(const T& other) const






	{













		return compare(other) > 0;

	}



































	/// \brief Returns true if "other" is greater than or equal to this object










	bool operator >=(const T& other) const






	{






































		return compare(other) >= 0;














	}

protected:
	/// \brief Destroy object
	///
	/// This class has nothing to destroy, but declaring the dtor
	/// virtual placates some compilers set to high warning levels.
	/// Protecting it ensures you can't delete subclasses through base
	/// class pointers, which makes no sense because this class isn't

	/// made for polymorphism.  It's just a mixin.



	virtual ~Comparable() { }



	/// \brief Compare this object to another of the same type
	///

	/// Returns < 0 if this object is "before" the other, 0 of they are
	/// equal, and > 0 if this object is "after" the other.
	virtual int compare(const T& other) const = 0;





};

}


#endif // !defined(MYSQLPP_COMPARABLE_H)








|
|

>
>
>
>
>
>
>
>


|
>
|
>
>
>
>
>
>
>
>

<
>
>
|
|
<
|


>
>
>
>
>
>
>
|
>
>
|
>
>
>
>
>
>
>
|
>
>
|
>
>
>
>
>
>
>

>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
>
>
|
>
>
>
>
>
>
|
>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>


>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
|
>
>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>

>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
|
>
>
>
>
>

>
>
>
>
|
>

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

>
>
>
>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
|
>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>

>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
|
>
>
>
>
>
>

>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>



|
|
|
|
|
|
>
|
>
>
>
|
>
>

|
|
>
|
<
<
>
>
>
>
>


|
>

|
>
21
22
23
24
25
26
27
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
56

57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
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
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
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
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
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
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
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
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706


707
708
709
710
711
712
713
714
715
716
717
718

 You should have received a copy of the GNU Lesser General Public
 License along with MySQL++; if not, write to the Free Software
 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
 USA
***********************************************************************/

#if !defined(MYSQLPP_DBDRIVER_H)
#define MYSQLPP_DBDRIVER_H

#include "common.h"

#include "options.h"

#include <typeinfo>

#include <limits.h>

namespace mysqlpp {

/// \brief Provides a thin abstraction layer over the underlying database 
/// client library.
///
/// This class does as little as possible to adapt between its public
/// interface and the interface required by the underlying C API.  That
/// is, in fact, its only mission.  The high-level interfaces indended
/// for use by MySQL++ users are in Connection, Query, Result, and
/// ResUse, all of which delegate the actual database communication to
/// an object of this type, created by Connection.  If you really need
/// access to the low-level database driver, get it via
/// Connection::driver(); don't create DBDriver objects directly.
///

/// Currently this is a concrete class for wrapping the MySQL C API.
/// In the future, it may be turned into an abstract base class, with
/// subclasses for different database server types.


class DBDriver
{
public:
	/// \brief Result code returned by next_result()
	enum nr_code {
		nr_more_results,	///< success, with more results to come
		nr_last_result,		///< success, last result received
		nr_error,			///< problem retrieving next result
		nr_not_supported	///< this C API doesn't support "next result"
	};

	/// \brief Create object
	DBDriver();

	/// \brief Duplicate an existing driver
	///
	/// \param other existing DBDriver object
	///
	/// This establishes a new database server connection with the same
	/// parameters as the other driver's.
	DBDriver(const DBDriver& other);

	/// \brief Destroy object
	virtual ~DBDriver();

	/// \brief Return the number of rows affected by the last query
	///
	/// Wraps \c mysql_affected_rows() in the MySQL C API.
	ulonglong affected_rows()
	{
		error_message_.clear();
		return mysql_affected_rows(&mysql_);
	}

	/// \brief Get database client library version
	///
	/// Wraps \c mysql_get_client_info() in the MySQL C API.
	std::string client_version() const
	{
		error_message_.clear();
		return mysql_get_client_info();
	}

	/// \brief Establish a new connection using the same parameters as
	/// an existing connection.
	///
	/// \param mysql existing MySQL C API connection object
	bool connect(const MYSQL& mysql);

	/// \brief Connect to database server
	///
	/// If you call this method on an object that is already connected
	/// to a database server, the previous connection is dropped and a
	/// new connection is established.
	virtual bool connect(const char* host, const char* socket_name,
			unsigned int port, const char* db, const char* user,
			const char* password);

	/// \brief Return true if we have an active connection to the
	/// database server.
	///
	/// This does not actually check whether the connection is viable,
	/// it just indicates whether there was previously a successful
	/// connect() call and no disconnect().  Call ping() to actually
	/// test the connection's viability.
	bool connected() const { return is_connected_; }

	/// \brief Establish a new connection as a copy of an existing one
	///
	/// \param other the connection to copy
	void copy(const DBDriver& other);

	/// \brief Ask the database server to create a database
	///
	/// \param db name of database to create
	///
	/// \return true if database was created successfully
	bool create_db(const char* db) const;

	/// \brief Seeks to a particualr row within the result set
	///
	/// Wraps mysql_data_seek() in MySQL C API.
	void data_seek(MYSQL_RES* res, ulonglong offset) const
	{
		error_message_.clear();
		mysql_data_seek(res, offset);
	}

	/// \brief Drop the connection to the database server
	///
	/// This method should only be used by MySQL++ library internals.
	/// Unless you use the default constructor, this object should
	/// always be connected.
	void disconnect();

	/// \brief Drop a database
	///
	/// \param db name of database to destroy
	///
	/// \return true if database was created successfully
	bool drop_db(const std::string& db) const;

	/// \brief Enable SSL-encrypted connection.
	///
	/// \param key the pathname to the key file
	/// \param cert the pathname to the certificate file
	/// \param ca the pathname to the certificate authority file
	/// \param capath directory that contains trusted SSL CA
	///        certificates in pem format.
	/// \param cipher list of allowable ciphers to use
	///
	/// \return False if call fails or the C API library wasn't compiled
	/// with SSL support enabled.
	///
	/// Must be called before connection is established.
	///
	/// Wraps \c mysql_ssl_set() in MySQL C API.
	bool enable_ssl(const char* key = 0, const char* cert = 0,
			const char* ca = 0, const char* capath = 0,
			const char* cipher = 0);

	/// \brief Return error message for last MySQL error associated with
	/// this connection.
	///
	/// Can return a MySQL++ DBDriver-specific error message if there
	/// is one.  If not, it simply wraps \c mysql_error() in the MySQL C API.
	const char* error()
	{
		return error_message_.length() ? error_message_.c_str() : mysql_error(&mysql_);
	}

	/// \brief Return last MySQL error number associated with this
	/// connection
	///
	/// Wraps \c mysql_errno() in the MySQL C API.
	int errnum() { return mysql_errno(&mysql_); }

	/// \brief Return a SQL-escaped version of the given character
	/// buffer
	///
	/// \param to character buffer to hold escaped version; must
	/// point to at least (length * 2 + 1) bytes
	/// \param from pointer to the character buffer to escape
	/// \param length number of characters to escape
	///
	/// \retval number of characters placed in escaped
	///
	/// Wraps \c mysql_real_escape_string() in the MySQL C API.
	///
	/// Proper SQL escaping takes the database's current character set 
	/// into account, however if a database connection isn't available
	/// DBDriver also provides a static version of this same method.
	///
	/// \sa escape_string_no_conn(char*, const char*, size_t)
	size_t escape_string(char* to, const char* from, size_t length)
	{
		error_message_.clear();
		return mysql_real_escape_string(&mysql_, to, from, 
				static_cast<unsigned long>(length));
	}

	/// \brief Return a SQL-escaped version of a character buffer
	///
	/// \param ps pointer to C++ string to hold escaped version; if
	/// original is 0, also holds the original data to be escaped
	/// \param original if given, pointer to the character buffer to
	/// escape instead of contents of *ps
	/// \param length if both this and original are given, number of
	/// characters to escape instead of ps->length()
	///
	/// \retval number of characters placed in *ps
	///
	/// This method has three basic operation modes:
	///
	/// - Pass just a pointer to a C++ string containing the original
	///   data to escape, plus act as receptacle for escaped version
	/// - Pass a pointer to a C++ string to receive escaped string plus
	///   a pointer to a C string to be escaped
	/// - Pass nonzero for all parameters, taking original to be a
	///   pointer to an array of char with given length; does not treat
	///   null characters as special
	///
	/// There's a degenerate fourth mode, where ps is zero: simply
	/// returns 0, because there is nowhere to store the result.
	///
	/// Note that if original is 0, we always ignore the length
	/// parameter even if it is nonzero.  Length always comes from
	/// ps->length() in this case.
	///
	/// ps is a pointer because if it were a reference, the other
	/// overload would be impossible to call: the compiler would
	/// complain that the two overloads are ambiguous because
	/// std::string has a char* conversion ctor. A nice bonus is that
	/// pointer syntax makes it clearer that the first parameter is an
	/// "out" parameter.
	///
	/// \see comments for escape_string(char*, const char*, size_t)
	/// for further details.
	/// 
	/// \sa escape_string_no_conn(std::string*, const char*, size_t)
	size_t escape_string(std::string* ps, const char* original,
			size_t length);

	/// \brief SQL-escapes the given string without reference to the 
	/// character set of a database server.
	///
	/// Wraps \c mysql_escape_string() in the MySQL C API.
	///
	/// \sa escape_string(char*, const char*, size_t)
	static size_t escape_string_no_conn(char* to, const char* from,
			size_t length)
	{
		return mysql_escape_string(to, from,
				static_cast<unsigned long>(length));
	}

	/// \brief SQL-escapes the given string without reference to the 
	/// character set of a database server.
	///
	/// \sa escape_string(std::string*, const char*, size_t),
	/// escape_string_no_conn(char*, const char*, size_t)
	static size_t escape_string_no_conn(std::string* ps, 
			const char* original = 0, size_t length = 0);

	/// \brief Executes the given query string
	///
	/// Wraps \c mysql_real_query() in the MySQL C API.
	bool execute(const char* qstr, size_t length)
	{
		error_message_.clear();
		return !mysql_real_query(&mysql_, qstr,
				static_cast<unsigned long>(length));
	}

	/// \brief Returns the next raw C API row structure from the given
	/// result set.
	///
	/// This is for "use" query result sets only.  "store" queries have
	/// all the rows already.
	///
	/// Wraps \c mysql_fetch_row() in MySQL C API.
	MYSQL_ROW fetch_row(MYSQL_RES* res) const
	{
		error_message_.clear();
		return mysql_fetch_row(res);
	}

	/// \brief Returns the lengths of the fields in the current row
	/// from a "use" query.
	///
	/// Wraps \c mysql_fetch_lengths() in MySQL C API.
	const unsigned long* fetch_lengths(MYSQL_RES* res) const
	{
		error_message_.clear();
		return mysql_fetch_lengths(res);
	}

	/// \brief Returns information about a particular field in a result
	/// set
	///
	/// \param res result set to fetch field information for
	/// \param i field number to fetch information for, if given
	///
	/// If i parameter is given, this call is like a combination of
	/// field_seek() followed by fetch_field() without the i parameter,
	/// which otherwise just iterates through the set of fields in the
	/// given result set.
	///
	/// Wraps \c mysql_fetch_field() and mysql_fetch_field_direct() in
	/// MySQL C API.  (Which one it uses depends on i parameter.)
	MYSQL_FIELD* fetch_field(MYSQL_RES* res, size_t i = UINT_MAX) const
	{
		error_message_.clear();
		return i == UINT_MAX ? mysql_fetch_field(res) :
				mysql_fetch_field_direct(res,
				static_cast<unsigned int>(i));
	}

	/// \brief Jumps to the given field within the result set
	///
	/// Wraps \c mysql_field_seek() in MySQL C API.
	void field_seek(MYSQL_RES* res, size_t field) const
	{
		error_message_.clear();
		mysql_field_seek(res, MYSQL_FIELD_OFFSET(field));
	}

	/// \brief Releases memory used by a result set
	///
	/// Wraps \c mysql_free_result() in MySQL C API.
	void free_result(MYSQL_RES* res) const
	{
		error_message_.clear();
		mysql_free_result(res);
	}

	/// \brief Return the connection options object
	st_mysql_options get_options() const { return mysql_.options; }

	/// \brief Get information about the IPC connection to the
	/// database server
	///
	/// String contains info about type of connection (e.g. TCP/IP,
	/// named pipe, Unix socket...) and the server hostname.
	///
	/// Wraps \c mysql_get_host_info() in the MySQL C API.
	std::string ipc_info()
	{
		error_message_.clear();
		return mysql_get_host_info(&mysql_);
	}

	/// \brief Get ID generated for an AUTO_INCREMENT column in the
	/// previous INSERT query.
	///
	/// \retval 0 if the previous query did not generate an ID.  Use
	/// the SQL function LAST_INSERT_ID() if you need the last ID
	/// generated by any query, not just the previous one.  This
	/// applies to stored procedure calls because this function returns
	/// the ID generated by the last query, which was a CALL statement,
	/// and CALL doesn't generate IDs.  You need to use LAST_INSERT_ID()
	/// to get the ID in this case.
	ulonglong insert_id()
	{
		error_message_.clear();
		return mysql_insert_id(&mysql_);
	}

	/// \brief Kill a MySQL server thread
	///
	/// \param tid ID of thread to kill
	///
	/// Wraps \c mysql_kill() in the MySQL C API.
	///
	/// \see thread_id()
	bool kill(unsigned long tid)
	{
		error_message_.clear();
		return !mysql_kill(&mysql_, tid);
	}

	/// \brief Returns true if there are unconsumed results from the
	/// most recent query.
	///
	/// Wraps \c mysql_more_results() in the MySQL C API.
	bool more_results()
	{
		error_message_.clear();
		#if MYSQL_VERSION_ID > 41000		// only in MySQL v4.1 +
			return mysql_more_results(&mysql_);
		#else
			return false;
		#endif
	}

	/// \brief Moves to the next result set from a multi-query
	///
	/// \return A code indicating whether we successfully found another
	/// result, there were no more results (but still success) or
	/// encountered an error trying to find the next result set.
	///
	/// Wraps \c mysql_next_result() in the MySQL C API, with
	/// translation of its return value from magic integers to nr_code
	/// enum values.
	nr_code next_result()
	{
		error_message_.clear();
		#if MYSQL_VERSION_ID > 41000		// only in MySQL v4.1 +
			switch (mysql_next_result(&mysql_)) {
				case 0:  return nr_more_results;
				case -1: return nr_last_result;
				default: return nr_error;
			}
		#else
			return nr_not_supported;
		#endif
	}

	/// \brief Returns the number of fields in the given result set
	///
	/// Wraps \c mysql_num_fields() in MySQL C API.
	int num_fields(MYSQL_RES* res) const
	{
		error_message_.clear();
		return mysql_num_fields(res);
	}

	/// \brief Returns the number of rows in the given result set
	///
	/// Wraps \c mysql_num_rows() in MySQL C API.
	ulonglong num_rows(MYSQL_RES* res) const
	{
		error_message_.clear();
		return mysql_num_rows(res);
	}

	/// \brief "Pings" the MySQL database
	///
	/// This function will try to reconnect to the server if the 
	/// connection has been dropped.  Wraps \c mysql_ping() in the MySQL C API.
	/// 
	/// \retval true if server is responding, regardless of whether we had
	/// to reconnect or not
	/// \retval false if either we already know the connection is down
	/// and cannot re-establish it, or if the server did not respond to
	/// the ping and we could not re-establish the connection.
	bool ping()
	{
		error_message_.clear();
		return !mysql_ping(&mysql_);
	}

	/// \brief Returns version number of MySQL protocol this connection
	/// is using
	///
	/// Wraps \c mysql_get_proto_info() in the MySQL C API.
	int protocol_version()
	{
		error_message_.clear();
		return mysql_get_proto_info(&mysql_);
	}

	/// \brief Returns information about the last executed query
	///
	/// Wraps \c mysql_info() in the MySQL C API
	std::string query_info();

	/// \brief Asks the database server to refresh certain internal data
	/// structures.
	///
	/// Wraps \c mysql_refresh() in the MySQL C API.  There is no
	/// corresponding interface for this in higher level MySQL++ classes
	/// because it was undocumented until recently, and it's a pretty
	/// low-level thing.  It's designed for things like MySQL
	/// Administrator.
	bool refresh(unsigned options)
	{
		error_message_.clear();
		return !mysql_refresh(&mysql_, options);
	}

	/// \brief Returns true if the most recent result set was empty
	///
	/// Wraps \c mysql_field_count() in the MySQL C API, returning true
	/// if it returns 0.
	bool result_empty()
	{
		error_message_.clear();
		return mysql_field_count(&mysql_) == 0;
	}

	/// \brief Asks the database server to switch to a different database
	bool select_db(const char* db)
	{
		error_message_.clear();
		return !mysql_select_db(&mysql_, db);
	}

	/// \brief Get the database server's version number
	///
	/// Wraps \c mysql_get_server_info() in the MySQL C API.
	std::string server_version()
	{
		error_message_.clear();
		return mysql_get_server_info(&mysql_);
	}

	/// \brief Sets a connection option
	///
	/// This is the database-independent high-level option setting
	/// interface that Connection::set_option() calls.  There are
	/// several private overloads that actually implement the option
	/// setting.
	///
	/// \see Connection::set_option(Option*) for commentary
	bool set_option(Option* o);

	/// \brief Set MySQL C API connection option
	///
	/// \internal Wraps \c mysql_options() in C API.
	bool set_option(mysql_option moption, const void* arg = 0)
	{
		error_message_.clear();
		return !mysql_options(&mysql_, moption,
				static_cast<const char*>(arg));
	}

	#if MYSQL_VERSION_ID >= 40101
	/// \brief Set MySQL C API connection option
	///
	/// \internal Wraps \c mysql_set_server_option() in C API.
	bool set_option(enum_mysql_set_option msoption)
	{
		error_message_.clear();
		return !mysql_set_server_option(&mysql_, msoption);
	}
	#endif

	/// \brief Set MySQL C API connection option
	///
	/// Manipulates the MYSQL.client_flag bit mask.  This allows these
	/// flags to be treated the same way as any other connection option,
	/// even though the C API handles them differently.
	bool set_option(unsigned int option, bool arg);

	/// \brief Same as set_option(), except that it won't override
	/// a previously-set option.
	bool set_option_default(Option* o)
	{
		const std::type_info& ti = typeid(o);
		for (OptionList::const_iterator it = applied_options_.begin();
				it != applied_options_.end();
				++it) {
			if (typeid(*it) == ti) {
				delete o;
				return "";		// option of this type already set
			}
		}

		return set_option(o);
	}

	/// \brief Ask database server to shut down.
	///
	/// User must have the "shutdown" privilege.
	///
	/// Wraps \c mysql_shutdown() in the MySQL C API.
	bool shutdown();

	/// \brief Returns the database server's status
	///
	/// String is similar to that returned by the \c mysqladmin
	/// \c status command.  Among other things, it contains uptime 
	/// in seconds, and the number of running threads, questions
	/// and open tables.
	///
	/// Wraps \c mysql_stat() in the MySQL C API.
	std::string server_status()
	{
		error_message_.clear();
		return mysql_stat(&mysql_);
	}

	/// \brief Saves the results of the query just execute()d in memory
	/// and returns a pointer to the MySQL C API data structure the
	/// results are stored in.
	///
	/// \sa use_result()
	///
	/// Wraps \c mysql_store_result() in the MySQL C API.
	MYSQL_RES* store_result()
	{
		error_message_.clear();
		return mysql_store_result(&mysql_);
	}

	/// \brief Returns true if MySQL++ and the underlying MySQL C API
	/// library were both compiled with thread awareness.
	///
	/// This is based in part on a MySQL C API function
	/// mysql_thread_safe().  We deliberately don't call this wrapper
	/// thread_safe() because it's a misleading name: linking to
	/// thread-aware versions of the MySQL++ and C API libraries doesn't
	/// automatically make your program "thread-safe".  See the
	/// <a href="../userman/threads.html">chapter on threads</a> in the
	/// user manual for more information and guidance.
	static bool thread_aware();

	/// \brief Tells the underlying MySQL C API library that this thread
	/// is done using the library.
	///
	/// This exists because the MySQL C API library allocates some per-thread
	/// memory which it doesn't release until you call this.
	static void thread_end()
	{
		#if MYSQL_VERSION_ID > 40000		// only in MySQL v4.0 +
			mysql_thread_end();
		#endif
	}

	/// \brief Returns the MySQL server thread ID for this connection
	///
	/// This has nothing to do with threading on the client side. It's
	/// a server-side thread ID, to be used with kill().
	unsigned long thread_id()
	{
		error_message_.clear();
		return mysql_thread_id(&mysql_);
	}

	/// \brief Tells the underlying C API library that the current
	/// thread will be using the library's services.
	///
	/// \retval True if there was no problem
	///
	/// The MySQL++ user manual's <a href="../userman/threads.html">chapter
	/// on threads</a> details two major strategies for dealing with
	/// connections in the face of threads.  If you take the simpler
	/// path, creating one DBDriver object per thread, it is never
	/// necessary to call this function; the underlying C API will call it
	/// for you when you establish the first database server connection
	/// from that thread.  If you use a more complex connection
	/// management strategy where it's possible for one thread to
	/// establish a connection that another thread uses, you must call
	/// this from each thread that can use the database before it creates
	/// any MySQL++ objects.  If you use a DBDriverPool object, this
	/// applies; DBDriverPool isn't smart enough to call this for you,
	/// and the MySQL C API won't do it, either.
	static bool thread_start()
	{
		#if MYSQL_VERSION_ID > 40000		// only in MySQL v4.0 +
			return !mysql_thread_init();
		#else
			return false;
		#endif
	}

	/// \brief Returns a result set from the last-executed query which
	/// we can walk through in linear fashion, which doesn't store all
	/// result sets in memory.
	///
	/// \sa store_result
	///
	/// Wraps \c mysql_use_result() in the MySQL C API.
	MYSQL_RES* use_result()
	{
		error_message_.clear();
		return mysql_use_result(&mysql_);
	}

protected:
	/// \brief Does things common to both connect() overloads, before
	/// each go and establish the connection in their different ways.
	bool connect_prepare();

	/// \brief Common implementation of set_option(Option*) and the
	/// delayed option setting code in connect_prepare()
	bool set_option_impl(Option* o);

private:
	/// \brief Data type of the list of applied connection options
	typedef std::deque<Option*> OptionList;

	/// \brief Iterator into an OptionList
	typedef OptionList::iterator OptionListIt;

	/// \brief Hidden assignment operator; we don't want to be copied
	/// that way.  What would it mean?
	DBDriver& operator=(const DBDriver&);



	MYSQL mysql_;
	bool is_connected_;
	OptionList applied_options_;
	OptionList pending_options_;
	mutable std::string error_message_;
};


} // end namespace mysqlpp

#endif // !defined(MYSQLPP_DBDRIVER_H)

Changes to lib/connection.cpp.

1









2



















3

4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26

27
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
56
57
58
59
60
61
62
63
64
65
66
67
68
69




70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88

89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
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
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
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
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
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
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
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
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
/***********************************************************************









 connection.cpp - Implements the Connection class.





















 Copyright (c) 1998 by Kevin Atkinson, (c) 1999-2001 by MySQL AB, and
 (c) 2004-2008 by Educational Technology Resources, Inc.  Others may
 also hold copyrights on code in this file.  See the CREDITS.txt file
 in the top directory of the distribution for details.

 This file is part of MySQL++.

 MySQL++ is free software; you can redistribute it and/or modify it
 under the terms of the GNU Lesser General Public License as published
 by the Free Software Foundation; either version 2.1 of the License, or
 (at your option) any later version.

 MySQL++ is distributed in the hope that it will be useful, but WITHOUT
 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
 License for more details.

 You should have received a copy of the GNU Lesser General Public
 License along with MySQL++; if not, write to the Free Software
 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
 USA
***********************************************************************/


#define MYSQLPP_NOT_HEADER
#include "connection.h"

#include "dbdriver.h"
#include "query.h"
#include "result.h"

using namespace std;

namespace mysqlpp {

Connection::Connection(bool te) :
OptionalExceptions(te),
driver_(new DBDriver()),
copacetic_(true)
{
}




Connection::Connection(const char* db, const char* server,
		const char* user, const char* password, unsigned int port) :
OptionalExceptions(),
driver_(new DBDriver()),
copacetic_(true)
{
	try {



		connect(db, server, user, password, port);
	}

	catch (...) {
		// Exception thrown from ctor causes dtor to not be called, so
		// we have to delete the DBDriver instance, else we'll leak it.
		delete driver_;
		throw;
	}
}


Connection::Connection(const Connection& other) :
OptionalExceptions(other.throw_exceptions()),
driver_(new DBDriver(*other.driver_))
{
	copy(other);
}






Connection::~Connection()
{
	disconnect();
	delete driver_;
}


void
Connection::build_error_message(const char* core)
{
	error_message_ = "Can't ";
	error_message_ += core;
	error_message_ += " while disconnected";
}


std::string

Connection::client_version() const
{
	return driver_->client_version();
}


bool
Connection::connect(const char* db, const char* server,
		const char* user, const char* password, unsigned int port)
{
	// Figure out what the server parameter means, then try to establish
	// the connection.
	error_message_.clear();
	string host, socket_name;
	copacetic_ = parse_ipc_method(server, host, port, socket_name) &&
			driver_->connect(host.c_str(),
			(socket_name.empty() ? 0 : socket_name.c_str()), port, db,
			user, password);

	// If it failed, decide how to tell the user
	if (!copacetic_ && throw_exceptions()) {
		throw ConnectionFailed(error(), errnum());
	}
	else {
		return copacetic_;
	}
}


bool
Connection::connected() const
{
	return driver_->connected();
}


void
Connection::copy(const Connection& other)
{
	error_message_.clear();
	set_exceptions(other.throw_exceptions());
	driver_->copy(*other.driver_);
}


ulonglong
Connection::count_rows(const std::string& table)
{
	error_message_.clear();
	Query q(this, throw_exceptions());
	q << "SELECT COUNT(*) FROM `" << table << '`';
	if (StoreQueryResult res = q.store()) {
		return res[0][0];
	}
	else {
		return 0;
	}
}


bool
Connection::create_db(const std::string& db)
{
	error_message_.clear();
	Query q(this, throw_exceptions());
	q << "CREATE DATABASE `" << db << '`';
	return q.exec();
}







void
Connection::disconnect()


{
	error_message_.clear();
	driver_->disconnect();
}


bool
Connection::drop_db(const std::string& db)
{
	error_message_.clear();
	Query q(this, throw_exceptions());
	q << "DROP DATABASE `" << db << '`';
	return q.exec();
}


int
Connection::errnum()
{
	return driver_->errnum();
}


const char*
Connection::error() const
{
	return error_message_.size() ? error_message_.c_str() : driver_->error();
}


std::string
Connection::ipc_info() const
{
	return driver_->ipc_info();
}


bool
Connection::kill(unsigned long tid) const
{
	error_message_.clear();
	return driver_->kill(tid);
}


Connection&
Connection::operator=(const Connection& rhs)
{
	copy(rhs);
	return *this;
}


bool
Connection::parse_ipc_method(const char* server, std::string& host,
		unsigned int& port, std::string& socket_name)
{
	// NOTE: This routine has no connection type knowledge.  It can only
	// recognize a 0 value for the server parameter.  All substantial
	// tests are delegated to our specialized subclasses, which figure
	// out what kind of connection the server address denotes.  We do
	// the platform-specific tests first as they're the most reliable.
	
	if (server == 0) {
		// Just take all the defaults
		return true;
	}
	else if (WindowsNamedPipeConnection::is_wnp(server)) {
		// Use Windows named pipes
		host = server;
		return true;
	}
	else if (UnixDomainSocketConnection::is_socket(server)) {
		// Use Unix domain sockets
		socket_name = server;
		return true;
	}


	else {
		// Failing above, it can only be some kind of TCP/IP address.
		host = server;
		return TCPConnection::parse_address(host, port, error_message_);
	}
}


bool





Connection::ping()

{
	if (connected()) {
		error_message_.clear();
		return driver_->ping();
	}
	else {
		// Not connected, and we've forgotten everything we need in
		// order to re-connect, if we once were connected.
		build_error_message("ping database server");
		return false;
	}
}


int
Connection::protocol_version() const
{
	return driver_->protocol_version();
}


Query
Connection::query(const char* qstr)
{
	return Query(this, throw_exceptions(), qstr);
}


Query
Connection::query(const std::string& qstr)
{
	return query(qstr.c_str());
}


bool
Connection::select_db(const std::string& db)

{
	error_message_.clear();
	if (connected()) {
		if (driver_->select_db(db.c_str())) {
			return true;
		}
		else {
			if (throw_exceptions()) {
				throw DBSelectionFailed(error(), errnum());
			}
			return false;
		}
	}
	else {
		build_error_message("select a database");
		if (throw_exceptions()) {
			throw DBSelectionFailed(error_message_.c_str());
		}

		return false;
	}
}



std::string
Connection::server_status() const
{
	return driver_->server_status();
}


std::string
Connection::server_version() const
{
	return driver_->server_version();
}


bool
Connection::set_option(Option* o)
{
	const std::type_info& oti = typeid(*o);
	if (driver_->set_option(o)) {
		error_message_.clear();
		return true;
	}
	else {
		error_message_ = driver_->error();
		if (throw_exceptions()) {
			throw BadOption(error_message_, oti);
		}
		return false;
	}
}


bool
Connection::shutdown()
{
	error_message_.clear();
	if (connected()) {
		if (driver_->shutdown()) {

			return true;
		}
		else {
			if (throw_exceptions()) {
				throw ConnectionFailed(error(), errnum());
			}
			return false;
		}
	}
	else {
		build_error_message("shutdown database server");
		if (throw_exceptions()) {
			throw ConnectionFailed(error_message_.c_str());
		}
		return false;
	}
}


bool
Connection::thread_aware()
{
	return DBDriver::thread_aware();
}


void
Connection::thread_end()
{
	DBDriver::thread_end();
}


unsigned long
Connection::thread_id()
{
	return driver_->thread_id();
}


bool
Connection::thread_start()
{
	return DBDriver::thread_start();
}

} // end namespace mysqlpp

|
>
>
>
>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

>
|
|
|
|



















>
|
<

|
|
<
|
<
|
|
|
<
<
<
<
<
<
|
>
>

<
<
<
<
<
|
<
>
>
>
|
<
>
|
<
<
<
<
<
<
|
|
<
<
<

|
<
>
>
>
>
|
|
<
|
|
|
|
|
|
<
<
<
<
<
<
<
|
|
<
>
|
|
<
<
|
|
<
<
<
<
<
<
<
<
<
<
<
<
|
<
<
<
|
|
|
|
|
<
<
<
<
|
<
<
|
|
<
<
|
<
<
|
<
|
|
<
<
<
<
<
<
<
<
|
<
<
|
|
|
|
<
<
<
<
|
<
<
<
|
>
>
>
>
>
|
|
|
>
>
|
<
<
|

|
|
<
|
<
<
<
<
<
|
|
<
<
<
<
<
|
|
<
<
<
<
<
|
|
<
<
<
<
<
|
|
<
<
<
<
<
<
|
|
<
<
<
<
|
|

|
|
<
<
|
<
<
<
<
<
|
<
|
<
|
|
<
<
<
|
|
|
|
<
<
>
>
|
|
|
<
<
<
|
|
|
>
>
>
>
>
|
>
|
<
<
<

<
<
<
<
<
|
<
|
|
<
|
<
<
<
|
|
<
<
<
<
<
|
|
<
<
<
<
<
|
|
<
<
>
|
<
<
<
<
|
<
<
<
<
<
<
<
<
<
<
<
|
>
|
|
<
|
|
>
|
<
<
<
<
|
|
<
<
<
<
<
|
|
|
<
|
<
<
<
<
<
<
<
|
<
<
<
<
<
|
|
<
<
<
<
|
<
>
|


|
<
<



<
<
<
<
|
<
<
<
|
|
<
<
|
<
<
|
<
<
|
<
<
<
|
<
<
<
<
<
|

|
<
<
|
<
<
|
<

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
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
56
57

58
59
60

61

62
63
64






65
66
67
68





69

70
71
72
73

74
75






76
77



78
79

80
81
82
83
84
85

86
87
88
89
90
91







92
93

94
95
96


97
98












99



100
101
102
103
104




105


106
107


108


109

110
111








112


113
114
115
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
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
191
192

193
194
195
196




197
198





199
200
201

202







203





204
205




206

207
208
209
210
211


212
213
214




215



216
217


218


219


220



221





222
223
224


225


226

227
/// \file insertpolicy.h
/// \brief Declares the InsertPolicy classes.
///
/// One creates an insert policy object to control how
/// Query::insertfrom() builds queries from collections of SSQLS
/// objects.  Policy objects are what cause Query::insertfrom() to
/// have different insertion behavior than Query::insert(iter, iter)
///
/// These templates use a class called the AccessController, which
/// is a stand-in for the mysqlpp::Transaction class and defaults to 
/// the Transaction class.  Since some of the InsertPolicy objects
/// (SizeThresholdInsertPolicy and MaxPacketInsertPolicy) may cause 
/// Query::insertfrom() to issue multiple SQL statements to perform
/// the insertion of all the objects in the container, and a failure in
/// one of these statements would leave the table in an indeterminate
/// state, the whole operation is wrapped in a transaction.
///
/// However, a transaction may not be desired if the calling code
/// is managing transactions, or transactions are not being used for 
/// some other reason.  In this case, the template can be instantiated
/// with the NoTransaction class.  It provides the complete Transaction
/// class interface, while doing nothing.
///
/// Where possible, you should use one of the provided insert
/// policy classes, but you can define your own if you need a behavior
/// that the provided set doesn't include.
/// 
/// This file is not meant to be included in end-user code.  It's
/// included in Query's public interface, since it is only used with
/// Query::insertfrom().  You access it as Query::InsertPolicy<T>

/***********************************************************************
 Copyright © 2008-2009 by AboveNet, Inc., and © 2009 by Educational
 Technology Resources, Inc.  Others may also hold copyrights on code
 in this file.  See the CREDITS file in the top directory of the
 distribution for details.

 This file is part of MySQL++.

 MySQL++ is free software; you can redistribute it and/or modify it
 under the terms of the GNU Lesser General Public License as published
 by the Free Software Foundation; either version 2.1 of the License, or
 (at your option) any later version.

 MySQL++ is distributed in the hope that it will be useful, but WITHOUT
 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
 License for more details.

 You should have received a copy of the GNU Lesser General Public
 License along with MySQL++; if not, write to the Free Software
 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
 USA
***********************************************************************/

#if !defined(MYSQLPP_INSERTPOLICY_H)
#define MYSQLPP_INSERTPOLICY_H


// Only allow these templates to be defined if they're being bodily
// included into class Query's definition.  They're in this separate

// file only for claity, so they don't get lost among the other

// definitions in class Query.  Without this, Doxygen will pick them
// up and treat them as a) outside namespace mysqlpp; and b) not member
// templates of class Query.  We also don't want end-users of the






// library to #include this file in their own code; these templates
// should only be used as mysqlpp::Query::*.
#if defined(MYSQLPP_DEFINE_INSERT_POLICY_TEMPLATES)








/// \brief An insert policy object that triggers a new INSERT
/// statement after a given number of rows have been inserted.
///
/// This policy is very lightweight, but is only reliable when you

/// can predict the size of each INSERT in advance.  The others do
/// more processing to reduce the risk of unpredictable row sizes.






template <class AccessController = Transaction>
class MYSQLPP_EXPORT RowCountInsertPolicy



{
public:

	/// \brief Constructor
	RowCountInsertPolicy(unsigned int rows) :
	cur_rows_(0),
	max_rows_(rows)
	{
	}


	/// \brief Destructor
	~RowCountInsertPolicy() { }

	/// \brief Can we add another object to the query?
	///







	/// \retval true if the object is allowed to be added to the
	/// INSERT statement

	template <class RowT>
	bool can_add(int, const RowT&)
	{


		if (++cur_rows_ > max_rows_) {
			cur_rows_ = 0;












			return false;



		}
		else {
			return true;
		}
	}







	/// \brief Alias for our access controller type
	typedef AccessController access_controller;





private:

	unsigned int cur_rows_;
	unsigned const int max_rows_;








};




/// \brief An insert policy object that triggers a new INSERT statement
/// after a size threshold for the length of the INSERT statement




/// is exceeded.



///
/// Although this insert policy isn't completely deterministic, it
/// avoids building the VALUES expression for the SSQLS object
/// passed in.
template <class AccessController = Transaction>
class MYSQLPP_EXPORT SizeThresholdInsertPolicy
{
public:
	/// \brief Constructor
	SizeThresholdInsertPolicy(int size) :
	size_(size)
	{


	}

	/// \brief Destructor
	~SizeThresholdInsertPolicy() { }







	/// \brief Can we add another object to the query?
	///





	/// \param size current length of the INSERT statement
	/// \param object the SSQLS object to be added





	///
	/// \retval true if the object is allowed to be added to the





	/// INSERT statement
	template <class RowT>






	bool can_add(int size, const RowT& object) const
	{




		return (size < size_);
	}

	/// \brief Alias for our access controller type
	typedef AccessController access_controller;








private:

	int size_;

};





/// \brief An insert policy object that triggers a new INSERT statement
/// if the object to be added would cause the statement to exceed
/// a maximum size.


///
/// This differs from the SizeThresholdInsertPolicy in that it builds
/// the VALUES expression and checks whether it would cause the
/// length of the INSERT statement to exceed the maximum size.
template <class AccessController = Transaction>



class MYSQLPP_EXPORT MaxPacketInsertPolicy
{
public:
	/// \brief Constructor
	///
	/// \param con connection object used for escaping text
	/// \param size the maximum allowed size for an INSERT
	///     statement
	MaxPacketInsertPolicy(Connection* con, int size) :
	conn_(con), size_(size)
	{



	}







	/// \brief Constructor
	///

	/// This version does not use a Connection* so it will not be



	/// able to take the character set into account when escaping
	/// the text.





	///
	/// \param size the maximum allowed size for an INSERT





	///     statement
	MaxPacketInsertPolicy(int size) :


	conn_(0), size_(size)
	{




	}












	/// \brief Destructor
	~MaxPacketInsertPolicy() { }


	/// \brief Can we add another object to the query?
	///
	/// \param size current length of the INSERT statement
	/// \param object the SSQLS object to be added




	///
	/// \retval true if the object is allowed to be added to the





	///     INSERT statement
	template <class RowT>
	bool can_add(int size, const RowT& object) const

	{







		if (size < size_) {





			// Haven't hit size threshold yet, so see if this next
			// item pushes it over the line.




			SQLStream s(conn_);

			s << ",(" << object.value_list() << ")";
			return (size_ - size) >= static_cast<int>(s.str().size());
		}
		else {
			// Already too much in query buffer!


			return false;
		}
	}








	/// \brief Alias for our access controller type
	typedef AccessController access_controller;





private:


	Connection* conn_;



	int size_;





};

#endif // defined(MYSQLPP_DEFINE_INSERT_POLICY_TEMPLATES)





#endif // !defined(MYSQLPP_INSERTPOLICY_H)


Changes to lib/connection.h.

1
2
3
4
5
6
7
8
9

10
11
12
13
14
15
16
17
18
/// \file connection.h
/// \brief Declares the Connection class.
///
/// Every program using MySQL++ must create a Connection object, which
/// manages information about the connection to the database server, and
/// performs connection-related operations once the connection is up.
/// Subordinate classes, such as Query and Row take their defaults as
/// to whether exceptions are thrown when errors are encountered from
/// the Connection object that created them, directly or indirectly.


/***********************************************************************
 Copyright (c) 1998 by Kevin Atkinson, (c) 1999-2001 by MySQL AB, and
 (c) 2004-2007 by Educational Technology Resources, Inc.  Others may
 also hold copyrights on code in this file.  See the CREDITS.txt file
 in the top directory of the distribution for details.

 This file is part of MySQL++.

|
|
<
<
<
<
<
<
<
>

<







1
2







3
4

5
6
7
8
9
10
11
/***********************************************************************
 printdata.h - Declares utility routines for printing out data in







	common forms, used by most of the example programs.


 Copyright (c) 1998 by Kevin Atkinson, (c) 1999-2001 by MySQL AB, and
 (c) 2004-2007 by Educational Technology Resources, Inc.  Others may
 also hold copyrights on code in this file.  See the CREDITS.txt file
 in the top directory of the distribution for details.

 This file is part of MySQL++.

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
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
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
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
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
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
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
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
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

 You should have received a copy of the GNU Lesser General Public
 License along with MySQL++; if not, write to the Free Software
 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
 USA
***********************************************************************/

#if !defined(MYSQLPP_CONNECTION_H)
#define MYSQLPP_CONNECTION_H

#include "common.h"

#include "noexceptions.h"
#include "options.h"

#include <string>

namespace mysqlpp {

#if !defined(DOXYGEN_IGNORE)
// Make Doxygen ignore this
class MYSQLPP_EXPORT Query;
class DBDriver;
#endif

/// \brief Manages the connection to the database server.
///
/// This class is a thick wrapper around DBDriver, adding high-level
/// error handling, utility functions, and abstraction away from
/// underlying C API details.

class MYSQLPP_EXPORT Connection : public OptionalExceptions
{
private:
	/// \brief Pointer to bool data member, for use by safe bool
	/// conversion operator.
	///
	/// \see http://www.artima.com/cppsource/safebool.html
	typedef bool Connection::*private_bool_type;

public:
	/// \brief Create object without connecting to the database server.
	///
	/// \param te if true, exceptions are thrown on errors
	Connection(bool te = true);

	/// \brief Create object and connect to database server in one step.
	///
	/// This constructor allows you to most fully specify the options
	/// used when connecting to the database server.
	///
	/// \param db name of database to select upon connection
	/// \param server specifies the IPC method and parameters for
	///     contacting the server; see below for details
	/// \param user user name to log in under, or 0 to use the user
	///		name this program is running under
	/// \param password password to use when logging in
	/// \param port TCP port number database server is listening on, or
	///		0 to use default value; note that you may also give this as
	///     part of the \c server parameter
	///
	/// The server parameter can be any of several different forms:
	///
	/// - \b 0: Let the database driver decide how to connect; usually
	///   some sort of localhost IPC method.
	/// - \b ".": On Windows, this means named pipes, if the server
	///   supports it
	/// - \b "/some/domain/socket/path": If the passed string doesn't
	///   match one of the previous alternatives and we're on a system
	///   that supports Unix domain sockets, MySQL++ will test it to see
	///   if it names one, and use it if we have permission.
	/// - \b "host.name.or.ip:port": If the previous test fails, or if
	///   the system doesn't support Unix domain sockets at all, it
	///   assumes the string is some kind of network address, optionally
	///   followed by a colon and port.  The name can be in dotted quad
	///   form, a host name, or a domain name.  The port can either be a
	///   TCP/IP port number or a symbolic service name.  If a port or
	///   service name is given here and a nonzero value is passed for
	///   the \c port parameter, the latter takes precedence.
	Connection(const char* db, const char* server = 0, const char* user = 0,
			const char* password = 0, unsigned int port = 0);

	/// \brief Establish a new connection using the same parameters as
	/// an existing connection.
	///
	/// \param other existing Connection object
	Connection(const Connection& other);

	/// \brief Destroy object
	virtual ~Connection();

	/// \brief Get version of library underpinning the current database
	/// driver.
	std::string client_version() const;

	/// \brief Connect to database after object is created.
	///
	/// It's better to use the connect-on-create constructor if you can.
	/// See its documentation for the meaning of these parameters.
	///
	/// If you call this method on an object that is already connected
	/// to a database server, the previous connection is dropped and a
	/// new connection is established.
	virtual bool connect(const char* db = 0, const char* server = 0,
			const char* user = 0, const char* password = 0,
			unsigned int port = 0);

	/// \brief Returns true if connection was established successfully
	///
	/// \return true if connection was established successfully
	bool connected() const;

	/// \brief Returns the number of rows in a table
	///
	/// \param table name of table whose rows you want counted
	///
	/// This is syntactic sugar for a \c SELECT \c COUNT(*)
	/// \c FROM \c table SQL query.
	ulonglong count_rows(const std::string& table);

	/// \brief Ask the database server to create a database
	///
	/// \param db name of database to create
	///
	/// \return true if database was created successfully
	bool create_db(const std::string& db);

	/// \brief Drop the connection to the database server
	void disconnect();

	/// \brief Returns a reference to the current database driver
	///
	/// \internal This exists mostly for the benefit of Query, Result
	/// and ResUse.  If there is something you want to use in the
	/// DBDriver interface, look for something similar in one of these
	/// classes instead.  If you still can't find it, send a message to
	/// the mailing list asking about it.  Unless you're doing something
	/// very low-level, there should never be a reason to use the 
	/// driver directly.
	DBDriver* driver() { return driver_; }

	/// \brief Asks the database server to drop (destroy) a database
	///
	/// \param db name of database to destroy
	///
	/// \return true if database was dropped successfully
	bool drop_db(const std::string& db);

	/// \brief Return last error number associated with this
	/// connection
	int errnum();

	/// \brief Return error message for last error associated with
	/// this connection.
	///
	/// Returns either a MySQL++-specific error message if one exists,
	/// or one from the current database driver otherwise.
	const char* error() const;

	/// \brief Get information about the IPC connection to the
	/// database server
	///
	/// String contains info about type of connection (e.g. TCP/IP,
	/// named pipe, Unix socket...) and the server hostname.
	std::string ipc_info() const;

	/// \brief Kill a database server thread
	///
	/// \param tid ID of thread to kill
	///
	/// \see thread_id()
	bool kill(unsigned long tid) const;

	/// \brief Test whether any error has occurred within the object.
	///
	/// Allows the object to be used in bool context, like this:
	///
	/// \code
	///	Connection conn;
	///	.... use conn
	///	if (conn) {
	///	    ... nothing bad has happened since last successful use
	///	}
	///	else {
	///	    ... some error has occurred
	///	}
	/// \endcode
	///
	/// Prior to MySQL++ v3, the object was always falsy when we
	/// weren't connected.  Now a true return simply indicates a lack of
	/// errors.  If you've been using this to test for whether the
	/// connection is still up, you need to call connected() instead.
	operator private_bool_type() const
	{
		return copacetic_ ? &Connection::copacetic_ : 0;
	}

	/// \brief Copy an existing Connection object's state into this
	/// object.
	Connection& operator=(const Connection& rhs);

	/// \brief "Pings" the database server
	///
	/// \retval true if server is responding
	/// \retval false if either we already know the connection is down
	/// and cannot re-establish it, or if the server did not respond to
	/// the ping and we could not re-establish the connection.
	bool ping();

	/// \brief Returns version number of the protocol the database
	/// driver uses to communicate with the server.
	int protocol_version() const;

	/// \brief Return a new query object.
	///
	/// The returned query object is tied to this connection object,
	/// so when you call a method like
	/// \link Query::execute() execute() \endlink
	/// on that object, the query is sent to the server this object
	/// is connected to.
	///
	/// \param qstr an optional query string for populating the
	/// new Query object
	Query query(const char* qstr = 0);

	/// \brief Return a new query object
	///
	/// \param qstr initial query string
	Query query(const std::string& qstr);

	/// \brief Change to a different database managed by the
	/// database server we are connected to.
	///
	/// \param db database to switch to
	///
	/// \retval true if we changed databases successfully
	bool select_db(const std::string& db);

	/// \brief Get the database server's version string
	std::string server_version() const;

	/// \brief Sets a connection option
	///
	/// \param o pointer to any derivative of Option allocated on
	/// the heap
	///
	/// Objects passed to this method and successfully set will be
	/// released when this Connection object is destroyed.  If an error
	/// occurs while setting the option the object will be deleted
	/// immediately.
	///
	/// Because there are so many Option subclasses, the actual effect
	/// of this function has a wide range.  This mechanism abstracts
	/// away many things that are unrelated down at the database driver
	/// level, hiding them behind a coherent, type-safe interface.
	///
	/// The rules about which options can be set, when, are up to the
	/// underlying database driver.  Some must be set before the
	/// connection is established because they can only be used during
	/// that connection setup process.  Others can be set at any time
	/// after the connection comes up.  If you get it wrong, you'll get
	/// a BadOption exception.
	///
	/// \retval true if option was successfully set
	bool set_option(Option* o);

	/// \brief Ask database server to shut down.
	bool shutdown();

	/// \brief Returns information about database server's status
	std::string server_status() const;

	/// \brief Returns true if both MySQL++ and database driver we're
	/// using were compiled with thread awareness.
	static bool thread_aware();

	/// \brief Tells the underlying database driver that this thread
	/// is done using the library.
	static void thread_end();

	/// \brief Returns the database server's thread ID for this connection
	///
	/// This has nothing to do with threading on the client side.  The
	/// only thing you can do with this value is pass it to kill().
	unsigned long thread_id();

	/// \brief Tells the underlying database driver that the current
	/// thread is now using its services.
	///
	/// It's not necessary to call this from the thread that creates
	/// the connection as it's done automatically.  This method exists
	/// for times when multiple threads may use this object; it allows
	/// the underlying database driver to set up any per-thread data
	/// structures it needs.
	///
	/// The MySQL++ user manual's <a href="../userman/threads.html">chapter
	/// on threads</a> details two major strategies for dealing with
	/// connections in the face of threads.  The Connection-per-thread
	/// option frees you from ever having to call this method.  The
	/// other documented strategy is to use ConnectionPool, which opens
	/// the possibility for one thread to create a connection that
	/// another uses, so you do need to call this method in that case,
	/// or with any other similar strategy.
	///
	/// \retval True if there was no problem
	static bool thread_start();

protected:
	/// \brief Build an error message in the standard form used whenever
	/// one of the methods can't succeed because we're not connected to
	/// the database server.
	void build_error_message(const char* core);

	/// \brief Establish a new connection as a copy of an existing one
	///
	/// \param other the connection to copy
	void copy(const Connection& other);

	/// \brief Extract elements from the server parameter in formats
	/// suitable for passing to DBDriver::connect().
	bool parse_ipc_method(const char* server, std::string& host,
			unsigned int& port, std::string& socket_name);

	//// Subclass data
	mutable std::string error_message_;	///< MySQL++ specific error, if any

private:
	DBDriver* driver_;
	bool copacetic_;
};


} // end namespace mysqlpp

// Not strictly required, but bring in our specialization subclasses
#include "tcp_connection.h"
#include "uds_connection.h"
#include "wnp_connection.h"

#endif // !defined(MYSQLPP_CONNECTION_H)








|
|

<
<
<
<
<
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
|
<
<
|
<
<
<
|
<
<
<
<
<
<
<
|
<
<
<
|
<
<
<
<
<
<
<
<
<
<
<
|
<
<
<
<
|
<
<
<
<
<
<
<
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<

<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
|

21
22
23
24
25
26
27
28
29
30





31

















































































































































































32


33



34







35



36











37




38







39



























40









































































41
42

 You should have received a copy of the GNU Lesser General Public
 License along with MySQL++; if not, write to the Free Software
 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
 USA
***********************************************************************/

#if !defined(MYSQLPP_PRINTDATA_H)
#define MYSQLPP_PRINTDATA_H






#include <mysql++.h>




















































































































































































void print_stock_header(int rows);



void print_stock_row(const mysqlpp::Row& r);







void print_stock_row(const mysqlpp::sql_char& item,



		mysqlpp::sql_bigint num, mysqlpp::sql_double weight,











		mysqlpp::sql_decimal price, const mysqlpp::sql_date& date);




void print_stock_rows(mysqlpp::StoreQueryResult& res);







void print_stock_table(mysqlpp::Query& query);





































































































#endif // !defined(MYSQLPP_PRINTDATA_H)

Changes to lib/cpool.cpp.

1
2
3

4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
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
56
57


58


59
60
61
62

63

64
65
66
67
68
69
70
71
72

73
74

75
76
77




78
79

80




81

82

83
84
85
86



87



88
89
90
91

92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108


109
110



111
112
113
114
115
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
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
191
192
193
194
195
196
197




198


199
200
201
202
203
204
205

206
207


208
209





210
211
212
213
214
215
216
217
218
219
220
221
222

/***********************************************************************
 cpool.cpp - Implements the ConnectionPool class.


 Copyright (c) 2007-2009 by Educational Technology Resources, Inc. and
 (c) 2007 by Jonathan Wakely.  Others may also hold copyrights on
 code in this file.  See the CREDITS.txt file in the top directory
 of the distribution for details.

 This file is part of MySQL++.

 MySQL++ is free software; you can redistribute it and/or modify it
 under the terms of the GNU Lesser General Public License as published
 by the Free Software Foundation; either version 2.1 of the License, or
 (at your option) any later version.

 MySQL++ is distributed in the hope that it will be useful, but WITHOUT
 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
 License for more details.

 You should have received a copy of the GNU Lesser General Public
 License along with MySQL++; if not, write to the Free Software
 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
 USA
***********************************************************************/

#include "cpool.h"

#include "connection.h"

#include <algorithm>

#include <functional>

namespace mysqlpp {


/// \brief Functor to test whether a given ConnectionInfo object is
/// "too old".
///

/// \internal This is a template only because ConnectionInfo is private.
/// Making it a template means the private type is only used at the point
/// of instantiation, where it is accessible.

template <typename ConnInfoT>



class TooOld : std::unary_function<ConnInfoT, bool>
{
public:
#if !defined(DOXYGEN_IGNORE)
	TooOld(unsigned int tmax) :
	min_age_(time(0) - tmax)
	{



	}





	bool operator()(const ConnInfoT& conn_info) const

	{
		return !conn_info.in_use && conn_info.last_used <= min_age_;
	}





#endif
private:
	time_t min_age_;
};





//// clear /////////////////////////////////////////////////////////////
// Destroy connections in the pool, either all of them (completely
// draining the pool) or just those not currently in use.  The public
// method shrink() is an alias for clear(false).

void
ConnectionPool::clear(bool all)

{
	ScopedLock lock(mutex_);	// ensure we're not interfered with


	PoolIt it = pool_.begin();
	while (it != pool_.end()) {




		if (all || !it->in_use) {
			remove(it++);

		}




		else {

			++it;

		}
	}
}








//// exchange //////////////////////////////////////////////////////////
// Passed connection is defective, so remove it from the pool and return
// a new one.


Connection*
ConnectionPool::exchange(const Connection* pc)
{
	// Don't grab the mutex first.  remove() and grab() both do.
	// Inefficient, but we'd have to hoist their contents up into this
	// method or extract a mutex-free version of each mechanism for
	// each, both of which are also inefficient.
	remove(pc);
	return grab();
}


//// find_mru //////////////////////////////////////////////////////////
// Find most recently used available connection.  Uses operator< for
// ConnectionInfo to order pool with MRU connection last.  Returns 0 if
// there are no connections not in use.



Connection*
ConnectionPool::find_mru()



{
	PoolIt mru = std::max_element(pool_.begin(), pool_.end());
	if (mru != pool_.end() && !mru->in_use) {
		mru->in_use = true;
		return mru->conn;
	}
	else {
		return 0;
	}
}






//// grab //////////////////////////////////////////////////////////////







Connection*

ConnectionPool::grab()
{
	ScopedLock lock(mutex_);	// ensure we're not interfered with
	remove_old_connections();
	if (Connection* mru = find_mru()) {


		return mru;
	}
	else {
		// No free connections, so create and return a new one.
		pool_.push_back(ConnectionInfo(create()));
		return pool_.back().conn;
	}
}





//// release ///////////////////////////////////////////////////////////

void
ConnectionPool::release(const Connection* pc)
{
	ScopedLock lock(mutex_);	// ensure we're not interfered with



	for (PoolIt it = pool_.begin(); it != pool_.end(); ++it) {

		if (it->conn == pc) {

			it->in_use = false;

			it->last_used = time(0);
			break;





		}


	}
}


//// remove ////////////////////////////////////////////////////////////

// 2 versions:
//
// First takes a Connection pointer, finds it in the pool, and calls
// the second.  It's public, because Connection pointers are all
// outsiders see of the pool.
//
// Second takes an iterator into the pool, destroys the referenced
// connection and removes it from the pool.  This is only a utility
// function for use by other class internals.



void
ConnectionPool::remove(const Connection* pc)
{
	ScopedLock lock(mutex_);	// ensure we're not interfered with



	for (PoolIt it = pool_.begin(); it != pool_.end(); ++it) {
		if (it->conn == pc) {
			remove(it);

			return;
		}
	}
}

void
ConnectionPool::remove(const PoolIt& it)
{
	// Don't grab the mutex.  Only called from other functions that do
	// grab it.
	destroy(it->conn);
	pool_.erase(it);

}




//// remove_old_connections ////////////////////////////////////////////
// Remove connections that were last used too long ago.

void
ConnectionPool::remove_old_connections()
{




	TooOld<ConnectionInfo> too_old(max_idle_time());



	PoolIt it = pool_.begin();
	while ((it = std::find_if(it, pool_.end(), too_old)) != pool_.end()) {
		remove(it++);
	}
}



//// safe_grab /////////////////////////////////////////////////////////



Connection*





ConnectionPool::safe_grab()
{
	Connection* pc;
	while (!(pc = grab())->ping()) {
		remove(pc);
		pc = 0;
	}
	return pc;
}


} // end namespace mysqlpp



|

>
|
<
|
|



















|
<
|


>
|




|
|
<
>
|
|
<
|
|
>
>
>
|
|
|
<
<
|
|
>
>
>

>
>
>
>
|
<
>
|
<
|
>
>
|
>
>
|
|
|
<
>
|
>
|

<
<
<
<

|
<
>

<
>
|
|
|
>
>
>
>
|
<
>
|
>
>
>
>
|
>
|
>
|
|
|

>
>
>

>
>
>
|
<
<

>
|
|

<
<
<
<
<
|



|
|
<
|
|
>
>
|
|
>
>
>

<
<
<
|
|
<
<
|
|
>
>
>
|
>
|
|
>
>
>
>
|
>
>
|
>
|
|
<
|
<
>
>
|
|
<
<
<
<
|
|
>
>
|
>
|
|

|
|

<
>
>

|
>
|
>
|
>
|
|
>
>
>
>
>
|
>
>




<
>
|
<
<
<
<
<
<
<
<
|
>
>
|
<
|
<
>
>
|
<
<
|
>
|
|
|
|
<

|

<
<
<
|
>
|
>
>
|
|
<
<

<
<
|
>
>
>
>
|
>
>
|
|
|
|
|
<
|
>
|
|
>
>
|
|
>
>
>
>
>
|
<
<
|
|
<

|



<

>
1
2
3
4
5

6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27

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
56
57
58
59
60

61
62

63
64
65
66
67
68
69
70
71

72
73
74
75
76




77
78

79
80

81
82
83
84
85
86
87
88
89

90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111


112
113
114
115
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
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
191
192
193
194

195
196








197
198
199
200

201

202
203
204


205
206
207
208
209
210

211
212
213



214
215
216
217
218
219
220


221


222
223
224
225
226
227
228
229
230
231
232
233
234

235
236
237
238
239
240
241
242
243
244
245
246
247
248


249
250

251
252
253
254
255

256
257
/***********************************************************************
 mystring.cpp - Implements the String class.

 Copyright (c) 1998 by Kevin Atkinson, (c) 1999-2001 by MySQL AB, and
 (c) 2004-2008 by Educational Technology Resources, Inc.  Others may

 also hold copyrights on code in this file.  See the CREDITS.txt file
 in the top directory of the distribution for details.

 This file is part of MySQL++.

 MySQL++ is free software; you can redistribute it and/or modify it
 under the terms of the GNU Lesser General Public License as published
 by the Free Software Foundation; either version 2.1 of the License, or
 (at your option) any later version.

 MySQL++ is distributed in the hope that it will be useful, but WITHOUT
 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
 License for more details.

 You should have received a copy of the GNU Lesser General Public
 License along with MySQL++; if not, write to the Free Software
 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
 USA
***********************************************************************/

#include "mystring.h"

#include "query.h"

#include <algorithm>
#include <stdexcept>
#include <string>

namespace mysqlpp {


char
String::at(size_type pos) const

{
	if (pos >= size()) {
		throw BadIndex("String", int(pos), int(size()));

	}
	else {
		return buffer_->data()[pos];
	}
}


int


String::compare(const String& other) const
{
	if (other.buffer_) {
		return compare(0, std::max(length(), other.length()),
				other.buffer_->data());
	}
	else {
		// Other object has no buffer, so we are greater unless empty or
		// we also have no buffer.
		return length() > 0 ? 1 : 0;	
	}

}



int
String::compare(const std::string& other) const
{
	return compare(0, std::max(length(), other.length()), other.data());
}


int

String::compare(size_type pos, size_type num, std::string& other) const
{
	return compare(pos, num, other.data());
}






int

String::compare(const char* other) const
{

	return compare(0, std::max(length(), strlen(other)), other);
}


int
String::compare(size_type pos, size_type num,
		const char* other) const
{
	if (buffer_ && other) {

		return strncmp(data() + pos, other, num);
	}
	else if (!other) {
		// Initted and non-empty is "greater than" uninitted
		return length() > 0 ? 1 : 0;
	}
	else {
		// This object has no buffer, so we are less than other object
		// unless it is empty.
		return other[0] == '\0' ? 0 : -1;
	}
}


#if !defined(DOXYGEN_IGNORE)
// Doxygen isn't smart enough to recognize these template
// specializations.  Maybe it's the MYSQLPP_EXPORT tags?

template <>
String
String::conv(String) const { return *this; }




template <>
bool
String::conv(bool) const
{





	return *this;	// delegate to operator bool
}


template <>
std::string

String::conv(std::string) const
{
	return buffer_ ? std::string(data(), length()) : std::string();
}


template <>
Date
String::conv(Date) const
{



	return buffer_ ? Date(c_str()) : Date();
}




template <>
DateTime
String::conv(DateTime) const
{
	return buffer_ ? DateTime(c_str()) : DateTime();
}


template <>
Time
String::conv(Time) const
{
	return buffer_ ? Time(c_str()) : Time();
}

#endif // !defined(DOXYGEN_IGNORE)



const char*

String::data() const
{
	return buffer_ ? buffer_->data() : 0;
}






String::const_iterator
String::end() const
{
	return buffer_ ? buffer_->data() + buffer_->length() : 0;
}


bool
String::escape_q() const
{

	return buffer_ ? buffer_->type().escape_q() : false;
}


bool
String::is_null() const
{
	return buffer_ ? buffer_->is_null() : false;
}


void
String::it_is_null()
{
	if (buffer_) {
		buffer_->set_null();
	}
	else {
		buffer_ = new SQLBuffer(0, 0, mysql_type_info::string_type, true);
	}
}



String::size_type
String::length() const








{
	return buffer_ ? buffer_->length() : 0;
}




bool
String::quote_q() const
{


	// If no buffer, it means we're an empty string, so we need to be 
	// quoted to be expressed properly in SQL.
	return buffer_ ? buffer_->type().quote_q() : true;
}



void
String::to_string(std::string& s) const
{



	if (buffer_) {
		s.assign(buffer_->data(), buffer_->length());
	}
	else {
		s.clear();
	}
}






/// \brief Stream insertion operator for String objects
///
/// This doesn't have anything to do with the automatic quoting and
/// escaping you get when using SQLTypeAdapter with Query.  The need to
/// use String with Query should be rare, since String generally comes
/// in result sets; it should only go back out as queries when using
/// result data in a new query.  Since SQLTypeAdapter has a conversion
/// ctor for String, this shouldn't be a problem.  It's just trading
/// simplicity for a tiny bit of inefficiency in a rare case.  And 
/// since String and SQLTypeAdapter can share a buffer, it's not all
/// that inefficient anyway.


std::ostream&
operator <<(std::ostream& o, const String& in)
{
	if (dynamic_cast<Query*>(&o)) {
		// We can just insert the raw data into the stream
		o.write(in.data(), in.length());
	}
	else {
		// Can't guess what sort of stream it is, so convert the String
		// to a std::string so we can use the formatted output method.
		// To see why this is necessary, change it to use write() only
		// (unformatted output) and then run simple2: notice that the
		// columnar output formatting is wrecked.
		std::string temp;


		in.to_string(temp);
		o << temp;

	}
	return o;
}




} // end namespace mysqlpp

Changes to lib/cpool.h.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
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
56

57



58
59
60


61



62
63
64
65


66





67
68
69
70
71
72

73


74

75
76
77
78

79
80
81


82
83
84
85
86






87
88
89
90
91

92



93
94



95
96
97

98
99
100
101
102
103

104
105
106


107
108
109
110
111
112
113

114
115
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


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



191
192
193
194
195



196



197
198
199
200
201
202
203
204
205
206
207
208

209



210

211
212
213
214
215
216
217
218

219
220
221


222



223
224
















225
226
227
228
229
230
231
232

233



234
235
236
237
238
239
240
241
242
243
244


245





246
247
248
249










250

251
252
253
254
255
/// \file cpool.h
/// \brief Declares the ConnectionPool class.

/***********************************************************************
 Copyright (c) 2007-2008 by Educational Technology Resources, Inc. and
 (c) 2007 by Jonathan Wakely.  Others may also hold copyrights on
 code in this file.  See the CREDITS.txt file in the top directory
 of the distribution for details.

 This file is part of MySQL++.

 MySQL++ is free software; you can redistribute it and/or modify it
 under the terms of the GNU Lesser General Public License as published
 by the Free Software Foundation; either version 2.1 of the License, or
 (at your option) any later version.

 MySQL++ is distributed in the hope that it will be useful, but WITHOUT
 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
 License for more details.

 You should have received a copy of the GNU Lesser General Public
 License along with MySQL++; if not, write to the Free Software
 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
 USA
***********************************************************************/

#if !defined(MYSQLPP_CPOOL_H)
#define MYSQLPP_CPOOL_H

#include "beemutex.h"

#include <list>

#include <assert.h>
#include <time.h>

namespace mysqlpp {

#if !defined(DOXYGEN_IGNORE)
// Make Doxygen ignore this



class MYSQLPP_EXPORT Connection;
#endif


/// \brief Manages a pool of connections for programs that need more
/// than one Connection object at a time, but can't predict how many
/// they need in advance.
///
/// This class is useful in programs that need to make multiple
/// simultaneous queries on the database; this requires multiple
/// Connection objects due to a hard limitation of the underlying

/// C API.  Connection pools are most useful in multithreaded programs,
/// but it can be helpful to have one in a single-threaded program as
/// well.  Sometimes it's necessary to get more data from the server
/// while in the middle of processing data from an earlier query; this
/// requires multiple connections.  Whether you use a pool or manage

/// connections yourself is up to you, but realize that this class



/// takes care of a lot of subtle details for you that aren't obvious.
///
/// The pool's policy for connection reuse is to always return the 


/// \em most recently used connection that's not being used right now.



/// This ensures that excess connections don't hang around any longer
/// than they must.  If the pool were to return the \em least recently
/// used connection, it would be likely to result in a large pool of
/// sparsely used connections because we'd keep resetting the last-used 


/// time of whichever connection is least recently used at that moment.






class MYSQLPP_EXPORT ConnectionPool
{
public:
	/// \brief Create empty pool
	ConnectionPool() { }




	/// \brief Destroy object

	///
	/// If the pool raises an assertion on destruction, it means our
	/// subclass isn't calling clear() in its dtor as it should.
	virtual ~ConnectionPool() { assert(empty()); }


	/// \brief Returns true if pool is empty
	bool empty() const { return pool_.empty(); }



	/// \brief Return a defective connection to the pool and get a new
	/// one back.
	///
	/// Call this on receiving a BadQuery exception, with errnum()






	/// equal to CR_SERVER_GONE_ERROR.  It means the server was
	/// restarted or otherwise dropped your connection to it, so the
	/// Connection object is no longer usable.  You can avoid the
	/// need to use this by setting the ReconnectOption in your grab()
	/// override, but perhaps there are other reasons to need to

	/// exchange a bad connection for a good one.



	///
	/// This function wraps grab(), not safe_grab(), even though that



	/// could return another dead connection.  The assumption is that if
	/// your code is smart enough to detect one bad connection, it should
	/// be smart enough to detect a whole string of them.  Worst case,

	/// the whole pool is bad -- remote server went away -- and we have
	/// to empty the pool and start re-filling it.
	///
	/// \param pc pointer to a Connection object to be returned to the
	/// pool and marked as unused.
	///

	/// \retval a pointer to a different Connection object; not
	/// guaranteed to still be connected!
	virtual Connection* exchange(const Connection* pc);



	/// \brief Grab a free connection from the pool.
	///
	/// This method creates a new connection if an unused one doesn't
	/// exist, and destroys any that have remained unused for too long.
	/// If there is more than one free connection, we return the most
	/// recently used one; this allows older connections to die off over

	/// time when the caller's need for connections decreases.
	///
	/// Do not delete the returned pointer.  This object manages the


	/// lifetime of connection objects it creates.
	///
	/// \retval a pointer to the connection



	virtual Connection* grab();













	/// \brief Return a connection to the pool
	///
	/// Marks the connection as no longer in use.
	///


	/// The pool updates the last-used time of a connection only on
	/// release, on the assumption that it was used just prior.  There's
	/// nothing forcing you to do it this way: your code is free to

	/// delay releasing idle connections as long as it likes.  You
	/// want to avoid this because it will make the pool perform poorly;
	/// if it doesn't know approximately how long a connection has
	/// really been idle, it can't make good judgements about when to
	/// remove it from the pool.
	///

	/// \param pc pointer to a Connection object to be returned to the



	/// pool and marked as unused.
	virtual void release(const Connection* pc);




	/// \brief Removes the given connection from the pool




	///
	/// If you mean to simply return a connection to the pool after
	/// you're finished using it, call release() instead.  This method
	/// is primarily for error handling: you somehow have figured out


	/// that the connection is defective, so want it destroyed and



	/// removed from the pool.  If you also want a different connection
	/// to retry your operation on, call exchange() instead.
	///
	/// \param pc pointer to a Connection object to be removed from
	/// the pool and destroyed
	void remove(const Connection* pc);






	/// \brief Grab a free connection from the pool, testing that it's
	/// connected before returning it.
	///
	/// This is just a wrapper around grab(), Connection::ping() and
	/// release(), and is thus less efficient than grab().  Use it only



	/// when it's possible for MySQL server connections to go away






	/// unexpectedly, such as when the DB server can be restarted out
	/// from under your application.
	///
	/// \retval a pointer to the connection
	virtual Connection* safe_grab();



	/// \brief Remove all unused connections from the pool











	void shrink() { clear(false); }



protected:
	/// \brief Drains the pool, freeing all allocated memory.
	///
	/// A derived class must call this in its dtor to avoid leaking all
	/// Connection objects still in existence.  We can't do it up at
	/// this level because this class's dtor can't call our subclass's
	/// destroy() method.
	///
	/// \param all if true, remove all connections, even those in use
	void clear(bool all = true);




	/// \brief Create a new connection
	///



	/// Subclasses must override this.


	///
	/// Essentially, this method lets your code tell ConnectionPool




	/// what server to connect to, what login parameters to use, what
	/// connection options to enable, etc.  ConnectionPool can't know

	/// any of this without your help.



	///
	/// \retval A connected Connection object
	virtual Connection* create() = 0;


	/// \brief Destroy a connection



	///
	/// Subclasses must override this.
	///
	/// This is for destroying the objects returned by create().
	/// Because we can't know what the derived class did to create the



	/// connection we can't reliably know how to destroy it.



	virtual void destroy(Connection*) = 0;

	/// \brief Returns the maximum number of seconds a connection is
	/// able to remain idle before it is dropped.
	///
	/// Subclasses must override this as it encodes a policy issue,
	/// something that MySQL++ can't declare by fiat.
	///
	/// \retval number of seconds before an idle connection is destroyed
	/// due to lack of use
	virtual unsigned int max_idle_time() = 0;


	/// \brief Returns the current size of the internal connection pool.



	size_t size() const { return pool_.size(); }


private:
	//// Internal types
	struct ConnectionInfo {
		Connection* conn;
		time_t last_used;
		bool in_use;


		ConnectionInfo(Connection* c) :
		conn(c),
		last_used(time(0)),


		in_use(true)



		{
		}

















		// Strict weak ordering for ConnectionInfo objects.
		// 
		// This ordering defines all in-use connections to be "less
		// than" those not in use.  Within each group, connections
		// less recently touched are less than those more recent.
		bool operator<(const ConnectionInfo& rhs) const
		{

			const ConnectionInfo& lhs = *this;



			return lhs.in_use == rhs.in_use ?
					lhs.last_used < rhs.last_used :
					lhs.in_use;
		}
	};
	typedef std::list<ConnectionInfo> PoolT;
	typedef PoolT::iterator PoolIt;

	//// Internal support functions
	Connection* find_mru();
	void remove(const PoolIt& it);


	void remove_old_connections();






	//// Internal data
	PoolT pool_;
	BeecryptMutex mutex_;










};


} // end namespace mysqlpp

#endif // !defined(MYSQLPP_CPOOL_H)

|
|

<
|
|
<
|



















<
|
<
|

|

<
<




|
>
>
>
|
|
>
|
|
<
<
<
<
|
|
>
|
|
<
|
|
>
|
>
>
>
|
|
|
>
>
|
>
>
>
|
|
|
|
>
>
|
>
>
>
>
>
|
|
|
<
<
|
>
|
>
>
|
>
|
|
<
|
>
|
<
|
>
>
|
|
|
<
|
>
>
>
>
>
>
|
|
|
|
<
>
|
>
>
>
|
|
>
>
>
|
|
|
>
|
|
<
|
|
<
>
|
|
|
>
>
|
<
<
|
|
|
<
>
|
<
|
>
>
|
|
|
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>

|
<
|
<
>
>
|
|
|
>
|
|
|
<
|
<
>
|
>
>
>
|
|
>
>
>
|
|
>
>
>
>
|
|
<
|
>
>
|
>
>
>
|
|
<
<
<
|
>
>
>
>
>
|
|
|
<
|
<
>
>
>
|
>
>
>
>
>
>
|
|
<
|
|
|
>
>
|
>
>
>
>
>
>
>
>
>
>
>
|
>
>
|
|
|
<
<
<
<
<
<
<
<
>
>
|
>
|
<
>
>
>
|
>
>
|
|
>
>
>
>
|
|
>
|
>
>
>
|
|
|
>
|
|
>
>
>
|
|
<
<
<
>
>
>
|
>
>
>
|

|
|
<
<
<
<
<
<
<
|
>
|
>
>
>
|
>
|
|
|
|
|
<
<
|
>
|
<
<
>
>
|
>
>
>
|
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
|
|
|
<
<
|
|
>
|
>
>
>
|
<
|
|
|
<
<

|
|
<
>
>
|
>
>
>
>
>
|
|
|
|
>
>
>
>
>
>
>
>
>
>
|
>


<
<
<
1
2
3

4
5

6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25

26

27
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
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79


80
81
82
83
84
85
86
87
88

89
90
91

92
93
94
95
96
97

98
99
100
101
102
103
104
105
106
107
108

109
110
111
112
113
114
115
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
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
191

192
193
194
195
196
197
198
199
200



201
202
203
204
205
206
207
208
209

210

211
212
213
214
215
216
217
218
219
220
221
222

223
224
225
226
227
228
229
230
231
232
233
234
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
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
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


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
372
373
374
375



/***********************************************************************
 options.cpp - Implements the Option class hierarchy.


 Copyright (c) 2007-2009 by Educational Technology Resources, Inc.
 Others may also hold copyrights on code in this file.  See the

 CREDITS file in the top directory of the distribution for details.

 This file is part of MySQL++.

 MySQL++ is free software; you can redistribute it and/or modify it
 under the terms of the GNU Lesser General Public License as published
 by the Free Software Foundation; either version 2.1 of the License, or
 (at your option) any later version.

 MySQL++ is distributed in the hope that it will be useful, but WITHOUT
 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
 License for more details.

 You should have received a copy of the GNU Lesser General Public
 License along with MySQL++; if not, write to the Free Software
 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
 USA
***********************************************************************/


#define MYSQLPP_NOT_HEADER

#include "options.h"

#include "dbdriver.h"




namespace mysqlpp {

#if !defined(DOXYGEN_IGNORE)
// We're hiding all the Option subclass internals from Doxygen.  All the
// upper-level classes are documented fully, and each leaf class itself
// is documented.  It's just the ctors and set() methods we're refusing
// to document over and over again.

Option::Error
CompressOption::set(DBDriver* dbd)
{
	return dbd->connected() ? Option::err_connected :




			dbd->set_option(MYSQL_OPT_COMPRESS) ?
				Option::err_NONE : Option::err_api_reject;
}



Option::Error
ConnectTimeoutOption::set(DBDriver* dbd)
{
	return dbd->connected() ? Option::err_connected :
			dbd->set_option(MYSQL_OPT_CONNECT_TIMEOUT, &arg_) ?
				Option::err_NONE : Option::err_api_reject;
}


Option::Error
FoundRowsOption::set(DBDriver* dbd)
{
	return dbd->connected() ? Option::err_connected :
			dbd->set_option(CLIENT_FOUND_ROWS, arg_) ?
				Option::err_NONE : Option::err_api_reject;
}


Option::Error
GuessConnectionOption::set(DBDriver* dbd)
{
#if MYSQL_VERSION_ID >= 40101
	return dbd->connected() ? Option::err_connected :
			dbd->set_option(MYSQL_OPT_GUESS_CONNECTION) ?
				Option::err_NONE : Option::err_api_reject;
#else
	return Option::err_api_limit;
#endif
}




Option::Error
IgnoreSpaceOption::set(DBDriver* dbd)
{
	return dbd->connected() ? Option::err_connected :
			dbd->set_option(CLIENT_IGNORE_SPACE, arg_) ?
				Option::err_NONE : Option::err_api_reject;
}



Option::Error
InitCommandOption::set(DBDriver* dbd)
{

	return dbd->connected() ? Option::err_connected :
			dbd->set_option(MYSQL_INIT_COMMAND, arg_.c_str()) ?
				Option::err_NONE : Option::err_api_reject;
}



Option::Error
InteractiveOption::set(DBDriver* dbd)
{
	return dbd->connected() ? Option::err_connected :
			dbd->set_option(CLIENT_INTERACTIVE, arg_) ?
				Option::err_NONE : Option::err_api_reject;
}


Option::Error
LocalFilesOption::set(DBDriver* dbd)

{
	return dbd->connected() ? Option::err_connected :
			dbd->set_option(CLIENT_LOCAL_FILES, arg_) ?
				Option::err_NONE : Option::err_api_reject;
}


Option::Error
LocalInfileOption::set(DBDriver* dbd)
{
	return dbd->connected() ? Option::err_connected :
			dbd->set_option(MYSQL_OPT_LOCAL_INFILE, &arg_) ?
				Option::err_NONE : Option::err_api_reject;
}



Option::Error
MultiResultsOption::set(DBDriver* dbd)

{
#if MYSQL_VERSION_ID >= 40101
	if (dbd->connected()) {
		return dbd->set_option(arg_ ? MYSQL_OPTION_MULTI_STATEMENTS_ON :
				MYSQL_OPTION_MULTI_STATEMENTS_OFF) ?
				Option::err_NONE : Option::err_api_reject;
	}


	else {
		return dbd->set_option(CLIENT_MULTI_RESULTS, arg_) ?
				Option::err_NONE : Option::err_api_reject;

	}
#else

	return Option::err_api_limit;
#endif
}


Option::Error
MultiStatementsOption::set(DBDriver* dbd)
{
#if MYSQL_VERSION_ID >= 40101
	if (dbd->connected()) {
		return dbd->set_option(arg_ ? MYSQL_OPTION_MULTI_STATEMENTS_ON :
				MYSQL_OPTION_MULTI_STATEMENTS_OFF) ?
				Option::err_NONE : Option::err_api_reject;
	}
	else {
		return dbd->set_option(CLIENT_MULTI_STATEMENTS, arg_) ?
				Option::err_NONE : Option::err_api_reject;
	}
#else
	return Option::err_api_limit;
#endif
}



Option::Error

NamedPipeOption::set(DBDriver* dbd)
{
	return dbd->connected() ? Option::err_connected :
			dbd->set_option(MYSQL_OPT_NAMED_PIPE) ?
				Option::err_NONE : Option::err_api_reject;
}


Option::Error

NoSchemaOption::set(DBDriver* dbd)

{
	return dbd->connected() ? Option::err_connected :
			dbd->set_option(CLIENT_NO_SCHEMA, arg_) ?
				Option::err_NONE : Option::err_api_reject;
}


#if MYSQL_VERSION_ID > 40000		// only in 4.0 +
Option::Error
ProtocolOption::set(DBDriver* dbd)
{
	return dbd->connected() ? Option::err_connected :
			dbd->set_option(MYSQL_OPT_PROTOCOL, &arg_) ?
				Option::err_NONE : Option::err_api_reject;
}
#endif



Option::Error
ReadDefaultFileOption::set(DBDriver* dbd)
{
	return dbd->connected() ? Option::err_connected :
			dbd->set_option(MYSQL_READ_DEFAULT_FILE, arg_.c_str()) ?
				Option::err_NONE : Option::err_api_reject;
}





Option::Error
ReadDefaultGroupOption::set(DBDriver* dbd)
{
	return dbd->connected() ? Option::err_connected :
			dbd->set_option(MYSQL_READ_DEFAULT_GROUP, arg_.c_str()) ?
				Option::err_NONE : Option::err_api_reject;
}



Option::Error

ReadTimeoutOption::set(DBDriver* dbd)
{
#if MYSQL_VERSION_ID >= 40101
	return dbd->connected() ? Option::err_connected :
			dbd->set_option(MYSQL_OPT_READ_TIMEOUT, &arg_) ?
				Option::err_NONE : Option::err_api_reject;
#else
	return Option::err_api_limit;
#endif
}



Option::Error
ReconnectOption::set(DBDriver* dbd)
{
#if MYSQL_VERSION_ID >= 50106
	// Option fixed in this version to work correctly whether set before
	// connection comes up, or after
	return dbd->set_option(MYSQL_OPT_RECONNECT, &arg_) ?
			Option::err_NONE : Option::err_api_reject;
#elif MYSQL_VERSION_ID >= 50013
	// Between the time the option was created in 5.0.13 and when it was
	// fixed in 5.1.6, it only worked correctly if set after initial
	// connection.  So, don't accept it if disconnected, even though API
	// does accept it; option gets reset when the connection comes up.
	return dbd->connected() ?
			dbd->set_option(MYSQL_OPT_RECONNECT, &arg_) ?
				Option::err_NONE : Option::err_api_reject :
				Option::err_disconnected;
#else
	return Option::err_api_limit;
#endif
}










Option::Error
ReportDataTruncationOption::set(DBDriver* dbd)
{
#if MYSQL_VERSION_ID >= 50003
	return dbd->connected() ? Option::err_connected :

			dbd->set_option(MYSQL_REPORT_DATA_TRUNCATION, &arg_) ?
				Option::err_NONE : Option::err_api_reject;
#else
	return Option::err_api_limit;
#endif
}


Option::Error
SecureAuthOption::set(DBDriver* dbd)
{
#if MYSQL_VERSION_ID >= 40101
	return dbd->connected() ? Option::err_connected :
			dbd->set_option(MYSQL_SECURE_AUTH, &arg_) ?
				Option::err_NONE : Option::err_api_reject;
#else
	return Option::err_api_limit;
#endif
}


Option::Error
SetCharsetDirOption::set(DBDriver* dbd)
{
	return dbd->connected() ? Option::err_connected :
			dbd->set_option(MYSQL_SET_CHARSET_DIR, arg_.c_str()) ?
				Option::err_NONE : Option::err_api_reject;
}





Option::Error
SetCharsetNameOption::set(DBDriver* dbd)
{
	return dbd->connected() ? Option::err_connected :
			dbd->set_option(MYSQL_SET_CHARSET_NAME, arg_.c_str()) ?
				Option::err_NONE : Option::err_api_reject;
}


Option::Error
SetClientIpOption::set(DBDriver* dbd)







{
#if MYSQL_VERSION_ID >= 40101
	return dbd->connected() ? Option::err_connected :
			dbd->set_option(MYSQL_SET_CLIENT_IP, arg_.c_str()) ?
				Option::err_NONE : Option::err_api_reject;
#else
	return Option::err_api_limit;
#endif
}


Option::Error
SharedMemoryBaseNameOption::set(DBDriver* dbd)


{
#if MYSQL_VERSION_ID >= 40100
	return dbd->connected() ? Option::err_connected :


			dbd->set_option(MYSQL_SHARED_MEMORY_BASE_NAME, arg_.c_str()) ?
				Option::err_NONE : Option::err_api_reject;
#else
	return Option::err_api_limit;
#endif
}


Option::Error
SslOption::set(DBDriver* dbd)
{
#if defined(HAVE_MYSQL_SSL_SET)
	return dbd->connected() ? Option::err_connected :
			dbd->enable_ssl(
				key_.size() ? key_.c_str() : 0,
				cert_.size() ? cert_.c_str() : 0,
				ca_.size() ? ca_.c_str() : 0,
				capath_.size() ? capath_.c_str() : 0,
				cipher_.size() ? cipher_.c_str() : 0) ?
				Option::err_NONE : Option::err_api_reject;
#else
	(void)dbd;
	return Option::err_api_limit;
#endif
}


Option::Error


UseEmbeddedConnectionOption::set(DBDriver* dbd)
{
#if MYSQL_VERSION_ID >= 40101
	return dbd->connected() ? Option::err_connected :
			dbd->set_option(MYSQL_OPT_USE_EMBEDDED_CONNECTION) ?
				Option::err_NONE : Option::err_api_reject;
#else
	return Option::err_api_limit;

#endif
}




Option::Error
UseRemoteConnectionOption::set(DBDriver* dbd)

{
#if MYSQL_VERSION_ID >= 40101
	return dbd->connected() ? Option::err_connected :
			dbd->set_option(MYSQL_OPT_USE_REMOTE_CONNECTION) ?
				Option::err_NONE : Option::err_api_reject;
#else
	return Option::err_api_limit;
#endif
}


Option::Error
WriteTimeoutOption::set(DBDriver* dbd)
{
#if MYSQL_VERSION_ID >= 40101
	return dbd->connected() ? Option::err_connected :
			dbd->set_option(MYSQL_OPT_WRITE_TIMEOUT, &arg_) ?
				Option::err_NONE : Option::err_api_reject;
#else
	return Option::err_api_limit;
#endif
}

#endif // !defined(DOXYGEN_IGNORE)

} // end namespace mysqlpp



Changes to lib/datetime.cpp.

1
2
3


4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
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
56

57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
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
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
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
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
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
311
312
313
314
315
316
317
318
319
320
321
322
323
/***********************************************************************
 datetime.cpp - Implements date and time classes compatible with MySQL's
	various date and time column types.



 Copyright (c) 1998 by Kevin Atkinson, (c) 1999-2001 by MySQL AB, and
 (c) 2004-2008 by Educational Technology Resources, Inc.  Others may
 also hold copyrights on code in this file.  See the CREDITS.txt file
 in the top directory of the distribution for details.

 This file is part of MySQL++.

 MySQL++ is free software; you can redistribute it and/or modify it
 under the terms of the GNU Lesser General Public License as published
 by the Free Software Foundation; either version 2.1 of the License, or
 (at your option) any later version.

 MySQL++ is distributed in the hope that it will be useful, but WITHOUT
 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
 License for more details.

 You should have received a copy of the GNU Lesser General Public
 License along with MySQL++; if not, write to the Free Software
 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
 USA
***********************************************************************/

#define MYSQLPP_NOT_HEADER
#include "common.h"

#include "datetime.h"
#include "stream2string.h"

#include <iomanip>

#include <stdlib.h>
#include <time.h>

using namespace std;

namespace mysqlpp {















static void






safe_localtime(struct tm* ptm, const time_t t)




































{








#if defined(MYSQLPP_HAVE_LOCALTIME_S)
















	// common.h detected localtime_s() from native RTL of VC++ 2005 and up
	localtime_s(ptm, &t);



#elif defined(HAVE_LOCALTIME_R)
	// autoconf detected POSIX's localtime_r() on this system






	localtime_r(&t, ptm);


















#else
	// No explicitly thread-safe localtime() replacement found.  This
	// may still be thread-safe, as some C libraries take special steps
	// within localtime() to get thread safety, such as TLS.
	memcpy(ptm, localtime(&t), sizeof(tm));

#endif
}


std::ostream& operator <<(std::ostream& os, const Date& d)
{
	char fill = os.fill('0');
	ios::fmtflags flags = os.setf(ios::right);
	os		<< setw(4) << d.year() << '-'
			<< setw(2) << static_cast<int>(d.month()) << '-'
			<< setw(2) << static_cast<int>(d.day());
	os.flags(flags);
	os.fill(fill);
	return os;
}


std::ostream& operator <<(std::ostream& os, const Time& t)
{
	char fill = os.fill('0');
	ios::fmtflags flags = os.setf(ios::right);
	os		<< setw(2) << static_cast<int>(t.hour()) << ':'
			<< setw(2) << static_cast<int>(t.minute()) << ':'
			<< setw(2) << static_cast<int>(t.second());
	os.flags(flags);
	os.fill(fill);
	return os;
}


std::ostream& operator <<(std::ostream& os, const DateTime& dt)
{
	if (dt.is_now()) {
		return os << "NOW()";
	}
	else {
		operator <<(os, Date(dt));
		os << ' ';
		return operator <<(os, Time(dt));
	}
}


Date::Date(time_t t)
{
	struct tm tm;
	safe_localtime(&tm, t);

	year_ = tm.tm_year + 1900;
	month_ = tm.tm_mon + 1;
	day_ = tm.tm_mday;
}


DateTime::DateTime(time_t t)
{
	struct tm tm;
	safe_localtime(&tm, t);

	year_ = tm.tm_year + 1900;
	month_ = tm.tm_mon + 1;
	day_ = tm.tm_mday;
	hour_ = tm.tm_hour;
	minute_ = tm.tm_min;
	second_ = tm.tm_sec;

	now_ = false;
}


Time::Time(time_t t)
{
	struct tm tm;
	safe_localtime(&tm, t);

	hour_ = tm.tm_hour;
	minute_ = tm.tm_min;
	second_ = tm.tm_sec;
}


const char*
Date::convert(const char* str)
{
	char num[5];

	num[0] = *str++;
	num[1] = *str++;
	num[2] = *str++;
	num[3] = *str++;
	num[4] = 0;
	year_ = static_cast<unsigned short>(strtol(num, 0, 10));
	if (*str == '-') str++;

	num[0] = *str++;
	num[1] = *str++;
	num[2] = 0;
	month_ = static_cast<unsigned char>(strtol(num, 0, 10));
	if (*str == '-') str++;

	num[0] = *str++;
	num[1] = *str++;
	num[2] = 0;
	day_ = static_cast<unsigned char>(strtol(num, 0, 10));

	return str;
}


const char*
Time::convert(const char* str)
{
	char num[5];

	num[0] = *str++;
	num[1] = *str++;
	num[2] = 0;
	hour_ = static_cast<unsigned char>(strtol(num,0,10));
	if (*str == ':') str++;

	num[0] = *str++;
	num[1] = *str++;
	num[2] = 0;
	minute_ = static_cast<unsigned char>(strtol(num,0,10));
	if (*str == ':') str++;

	num[0] = *str++;
	num[1] = *str++;
	num[2] = 0;
	second_ = static_cast<unsigned char>(strtol(num,0,10));

	return str;
}


const char*
DateTime::convert(const char* str)
{
	Date d;
	str = d.convert(str);
	year_ = d.year();
	month_ = d.month();
	day_ = d.day();
	
	if (*str == ' ') ++str;

	Time t;
	str = t.convert(str);
	hour_ = t.hour();
	minute_ = t.minute();
	second_ = t.second();

	now_ = false;
	
	return str;
}


int
Date::compare(const Date& other) const
{
	if (year_ != other.year_) return year_ - other.year_;
	if (month_ != other.month_) return month_ - other.month_;
	return day_ - other.day_;
}


int
Time::compare(const Time& other) const
{
	if (hour_ != other.hour_) return hour_ - other.hour_;
	if (minute_ != other.minute_) return minute_ - other.minute_;
	return second_ - other.second_;
}


int
DateTime::compare(const DateTime& other) const
{
	if (now_ && other.now_) {
		return 0;
	}
	else {
		Date d(*this), od(other);
		Time t(*this), ot(other);

		if (int x = d.compare(od)) {
			return x;
		}
		else {
			return t.compare(ot);
		}
	}
}


Date::operator std::string() const
{
	return stream2string(*this);
}


DateTime::operator std::string() const
{
	return stream2string(*this);
}


Time::operator std::string() const
{
	return stream2string(*this);
}


Date::operator time_t() const
{
	struct tm tm;
	safe_localtime(&tm, time(0));

	tm.tm_mday = day_;
	tm.tm_mon = month_ - 1;
	tm.tm_year = year_ - 1900;
	tm.tm_isdst = -1;

	return mktime(&tm);
}


DateTime::operator time_t() const
{
	if (now_) {
		// Many factors combine to make it almost impossible for this
		// case to return the same value as you'd get if you used this
		// in a query.  But, you gotta better idea than to return the
		// current time for an object initialized with the value "now"?
		return time(0);
	}
	else {
		struct tm tm;
		tm.tm_sec = second_;
		tm.tm_min = minute_;
		tm.tm_hour = hour_;
		tm.tm_mday = day_;
		tm.tm_mon = month_ - 1;
		tm.tm_year = year_ - 1900;
		tm.tm_isdst = -1;

		return mktime(&tm);
	}
}


Time::operator time_t() const
{
	struct tm tm;
	safe_localtime(&tm, time(0));

	tm.tm_sec = second_;
	tm.tm_min = minute_;
	tm.tm_hour = hour_;
	tm.tm_isdst = -1;

	return mktime(&tm);
}

} // end namespace mysqlpp


|
|
>
>

|
|
|
|




















|

|
<

|
<
|
<

<



>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
|
>
>
>
|
<
>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

<
<
<
<
>




<
<
<
<
<
<
<
<
<
<
<
|
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
|
|
<
<
<
<
<
<
<
<
|
<
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
|
<
<
|
|
<
<
|
<
<
<
<
|
|
<
<
<
<
|
|
<
<
<
<
|
|
<
<
<
<
|
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<




1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
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
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
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
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
/***********************************************************************
 beemutex.cpp - Implements the BeecryptMutex class.  The name comes
	from the fact that we lifted this essentially intact from the
	Beecrypt library, which is also LGPL.  See beecrypt.h for the list
	of changes we made on integrating it into MySQL++.

 Copyright (c) 2004 Beeyond Software Holding BV and (c) 2007 by
 Educational Technology Resources, Inc.  Others may also hold
 copyrights on code in this file.  See the CREDITS.txt file in the
 top directory of the distribution for details.

 This file is part of MySQL++.

 MySQL++ is free software; you can redistribute it and/or modify it
 under the terms of the GNU Lesser General Public License as published
 by the Free Software Foundation; either version 2.1 of the License, or
 (at your option) any later version.

 MySQL++ is distributed in the hope that it will be useful, but WITHOUT
 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
 License for more details.

 You should have received a copy of the GNU Lesser General Public
 License along with MySQL++; if not, write to the Free Software
 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
 USA
***********************************************************************/

#define MYSQLPP_NOT_HEADER
#include "beemutex.h"

#include "common.h"


#include <errno.h>

#include <string.h>




namespace mysqlpp {

#define ACTUALLY_DOES_SOMETHING
#if defined(HAVE_PTHREAD)
	typedef pthread_mutex_t bc_mutex_t;
#elif defined(HAVE_SYNCH_H)
#	include <synch.h>
	typedef mutex_t bc_mutex_t;
#elif defined(MYSQLPP_PLATFORM_WINDOWS)
	typedef HANDLE bc_mutex_t;
#else
// No supported mutex type found, so class becomes a no-op.
#	undef ACTUALLY_DOES_SOMETHING
#endif

#if defined(ACTUALLY_DOES_SOMETHING)
	static bc_mutex_t* impl_ptr(void* p)
			{ return static_cast<bc_mutex_t*>(p); }
#	if defined(MYSQLPP_PLATFORM_WINDOWS)
		static bc_mutex_t impl_val(void* p)
				{ return *static_cast<bc_mutex_t*>(p); }
#	endif
#endif


BeecryptMutex::BeecryptMutex() throw (MutexFailed)
#if defined(ACTUALLY_DOES_SOMETHING)
	: pmutex_(new bc_mutex_t)
#endif
{
#if defined(MYSQLPP_PLATFORM_WINDOWS)
	*impl_ptr(pmutex_) = CreateMutex((LPSECURITY_ATTRIBUTES) 0, FALSE,
			(LPCTSTR) 0);
	if (!impl_val(pmutex_))
		throw MutexFailed("CreateMutex failed");
#else
#	if HAVE_SYNCH_H || HAVE_PTHREAD
	register int rc;
#	endif
#	if HAVE_PTHREAD
		if ((rc = pthread_mutex_init(impl_ptr(pmutex_), 0)))
			throw MutexFailed(strerror(rc));
#	elif HAVE_SYNCH_H
		if ((rc = mutex_init(impl_ptr(pmutex_), USYNC_THREAD, 0)))
			throw MutexFailed(strerror(rc));
#	endif
#endif
}


BeecryptMutex::~BeecryptMutex()
{
#if defined(ACTUALLY_DOES_SOMETHING)
#	if defined(MYSQLPP_PLATFORM_WINDOWS)
		CloseHandle(impl_val(pmutex_));
#	elif HAVE_PTHREAD
		pthread_mutex_destroy(impl_ptr(pmutex_));
#	elif HAVE_SYNCH_H
		mutex_destroy(impl_ptr(pmutex_));
#	endif

	delete impl_ptr(pmutex_);
#endif
}


void
BeecryptMutex::lock() throw (MutexFailed)
{
#if defined(MYSQLPP_PLATFORM_WINDOWS)
	if (WaitForSingleObject(impl_val(pmutex_), INFINITE) == WAIT_OBJECT_0)
		return;
	throw MutexFailed("WaitForSingleObject failed");
#else
#	if HAVE_SYNCH_H || HAVE_PTHREAD
	register int rc;
#	endif
#	if HAVE_PTHREAD
		if ((rc = pthread_mutex_lock(impl_ptr(pmutex_))))
			throw MutexFailed(strerror(rc));
#	elif HAVE_SYNCH_H
		if ((rc = mutex_lock(impl_ptr(pmutex_))))
			throw MutexFailed(strerror(rc));
#	endif
#endif
}


bool
BeecryptMutex::trylock() throw (MutexFailed)
{
#if defined(ACTUALLY_DOES_SOMETHING)

#	if defined(MYSQLPP_PLATFORM_WINDOWS)
		switch (WaitForSingleObject(impl_val(pmutex_), 0)) {
			case WAIT_TIMEOUT:
				return false;
			case WAIT_OBJECT_0:
				return true;
			default:
				throw MutexFailed("WaitForSingleObbject failed");
		}
#	else
		register int rc;
#		if HAVE_PTHREAD
			if ((rc = pthread_mutex_trylock(impl_ptr(pmutex_))) == 0)
				return true;
			if (rc == EBUSY)
				return false;
			throw MutexFailed(strerror(rc));
#		elif HAVE_SYNCH_H
			if ((rc = mutex_trylock(impl_ptr(pmutex_))) == 0)
				return true;
			if (rc == EBUSY)
				return false;
			throw MutexFailed(strerror(rc));
#		endif
#	endif
#else




	return true;		// no-op build, so always succeed
#endif
}













void
BeecryptMutex::unlock() throw (MutexFailed)




















































































































{
#if defined(MYSQLPP_PLATFORM_WINDOWS)








	if (!ReleaseMutex(impl_val(pmutex_)))

		throw MutexFailed("ReleaseMutex failed");




































#else


#	if HAVE_SYNCH_H || HAVE_PTHREAD
		register int rc;


#	endif




#	if HAVE_PTHREAD
		if ((rc = pthread_mutex_unlock(impl_ptr(pmutex_))))




			throw MutexFailed(strerror(rc));
#	elif HAVE_SYNCH_H




		if ((rc = mutex_unlock(impl_ptr(pmutex_))))
			throw MutexFailed(strerror(rc));




#	endif
#endif

















































}

} // end namespace mysqlpp

Changes to lib/datetime.h.

1
2
3



4
5
6
7

8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
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
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105

106
107
108
109
110
111
112
113
114
115
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
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
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214

215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
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


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
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
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
372
373
374
375
376
377
378
379
380
381
382
383
384



385

386
387

388

389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462

/// \file datetime.h
/// \brief Declares classes to add SQL-compatible date and time
/// types to C++'s type system.




/***********************************************************************
 Copyright (c) 1998 by Kevin Atkinson, (c) 1999-2001 by MySQL AB, and
 (c) 2004-2008 by Educational Technology Resources, Inc.  Others may

 also hold copyrights on code in this file.  See the CREDITS.txt file
 in the top directory of the distribution for details.

 This file is part of MySQL++.

 MySQL++ is free software; you can redistribute it and/or modify it
 under the terms of the GNU Lesser General Public License as published
 by the Free Software Foundation; either version 2.1 of the License, or
 (at your option) any later version.

 MySQL++ is distributed in the hope that it will be useful, but WITHOUT
 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
 License for more details.

 You should have received a copy of the GNU Lesser General Public
 License along with MySQL++; if not, write to the Free Software
 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
 USA
***********************************************************************/

#if !defined(MYSQLPP_DATETIME_H)
#define MYSQLPP_DATETIME_H

#include "common.h"

#include "comparable.h"

#include <string>
#include <iostream>

namespace mysqlpp {

/// \brief C++ form of SQL's DATETIME type.
///
/// This object exists primarily for conversion purposes.  You can
/// initialize it in several different ways, and then convert the object
/// to SQL string form, extract the individual y/m/d h:m:s values,
/// convert it to C's time_t, etc.


class MYSQLPP_EXPORT DateTime : public Comparable<DateTime>
{
public:
	/// \brief Default constructor
	DateTime() :
	Comparable<DateTime>(),
	year_(0),
	month_(0),
	day_(0),
	hour_(0),
	minute_(0),
	second_(0),
	now_(true)
	{
	}

	/// \brief Initialize object from discrete y/m/d h:m:s values.
	///
	/// \param y year, 1000-9999
	/// \param mon month, 1-12
	/// \param d day of month, 1-31
	/// \param h hour, 0-23
	/// \param min minute, 0-59
	/// \param s second, 0-59
	DateTime(unsigned short y, unsigned char mon, unsigned char d,
			unsigned char h, unsigned char min, unsigned char s) :
	Comparable<DateTime>(),
	year_(y),
	month_(mon),
	day_(d),
	hour_(h),
	minute_(min),
	second_(s),
	now_(false)
	{
	}
	
	/// \brief Initialize object as a copy of another Date
	DateTime(const DateTime& other) :
	Comparable<DateTime>(),
	year_(other.year_),
	month_(other.month_),
	day_(other.day_),
	hour_(other.hour_),
	minute_(other.minute_),
	second_(other.second_),
	now_(other.now_)
	{
	}

	/// \brief Initialize object from a C string containing a SQL
	/// date-and-time string
	///
	/// String must be in the HH:MM:SS format.  It doesn't have to be
	/// zero-padded.
	explicit DateTime(const char* str) { convert(str); }
	
	/// \brief Initialize object from a C++ string containing a

	/// SQL date-and-time string
	///
	/// This works with any stringish class that declares a c_str()
	/// member function: std::string, mysqlpp::String...
	///
	/// \sa DateTime(const char*)
	template <class Str>
	explicit DateTime(const Str& str)
	{
		convert(str.c_str());
	}

	/// \brief Initialize object from a \c time_t
	explicit DateTime(time_t t);

	/// \brief Compare this object to another.
	///
	/// Returns < 0 if this object is before the other, 0 of they are
	/// equal, and > 0 if this object is after the other.
	int compare(const DateTime& other) const;

	/// \brief Parse a SQL date and time string into this object.
	const char* convert(const char*);

	/// \brief Get the date/time value's day part, 1-31
	unsigned char day() const { return day_; }

	/// \brief Change the date/time value's day part, 1-31
	void day(unsigned char d) { day_ = d; now_ = false; }

	/// \brief Get the date/time value's hour part, 0-23
	unsigned char hour() const { return hour_; }

	/// \brief Change the date/time value's hour part, 0-23
	void hour(unsigned char h) { hour_ = h; now_ = false; }

	/// \brief Returns true if object will evaluate to SQL "NOW()" on
	/// conversion to string.
	bool is_now() const { return now_; }

	/// \brief Get the date/time value's minute part, 0-59
	unsigned char minute() const { return minute_; }

	/// \brief Change the date/time value's minute part, 0-59
	void minute(unsigned char m) { minute_ = m; now_ = false; }

	/// \brief Get the date/time value's month part, 1-12
	unsigned char month() const { return month_; }

	/// \brief Change the date/time value's month part, 1-12
	void month(unsigned char m) { month_ = m; now_ = false; }

	/// \brief Factory to create an object instance that will convert
	/// to SQL "NOW()" on insertion into a query
	///
	/// This is just syntactic sugar around the default ctor
	static DateTime now() { return DateTime(); }

	/// \brief Convert to std::string
	operator std::string() const;

	/// \brief Convert to time_t
	operator time_t() const;

	/// \brief Get the date/time value's second part, 0-59
	unsigned char second() const { return second_; }

	/// \brief Change the date/time value's second part, 0-59
	void second(unsigned char s) { second_ = s; now_ = false; }

	/// \brief Return our value in std::string form
	std::string str() const { return *this; }

	/// \brief Get the date/time value's year part
	///


	/// There's no trickery here like in some date/time implementations
	/// where you have to add 1900 or something like that.  It simply
	/// returns the year in natural form, in the range 1000-9999.
	unsigned short year() const { return year_; }

	/// \brief Change the date/time value's year part
	///
	/// Pass the year value normally; we don't optimize the value by
	/// subtracting 1900 like some other date/time implementations.
	void year(unsigned short y) { year_ = y; now_ = false; }

private:
	unsigned short year_;	///< the year, as a simple integer
	unsigned char month_;	///< the month, 1-12
	unsigned char day_;		///< the day, 1-31
	unsigned char hour_;	///< the hour, 0-23 (not 0-255 as in Time!)
	unsigned char minute_;	///< the minute, 0-59
	unsigned char second_;	///< the second, 0-59

	bool now_;	///< true if object not initialized with explicit value
};


/// \brief Returns a DateTime object that, when inserted into query
/// will yield a SQL "NOW()" function call.
inline DateTime NOW() { return DateTime(); }


/// \brief Inserts a DateTime object into a C++ stream in a
/// SQL-compatible format.
///
/// The date and time are inserted into the stream, in that order,
/// with a space between them.
///

/// \param os stream to insert date and time into
/// \param dt date/time object to insert into stream
MYSQLPP_EXPORT std::ostream& operator <<(std::ostream& os,
		const DateTime& dt);


/// \brief C++ form of SQL's DATE type.
///
/// Objects of this class can be inserted into streams, and
/// initialized from SQL DATE strings.
class MYSQLPP_EXPORT Date : public Comparable<Date>
{
public:
	/// \brief Default constructor
	Date() : year_(0), month_(0), day_(0) { }

	/// \brief Initialize object
	///
	/// \param y year, 1000-9999
	/// \param m month, 1-12
	/// \param d day of month, 1-31
	Date(unsigned short y, unsigned char m, unsigned char d) :
	Comparable<Date>(),
	year_(y),
	month_(m),
	day_(d)
	{
	}
	
	/// \brief Initialize object as a copy of another Date
	Date(const Date& other) :
	Comparable<Date>(),
	year_(other.year_),
	month_(other.month_),
	day_(other.day_)
	{
	}

	/// \brief Initialize object from date part of date/time object
	Date(const DateTime& other) :
	Comparable<Date>(),
	year_(other.year()),
	month_(other.month()),
	day_(other.day())
	{
	}

	/// \brief Initialize object from a C string containing a date
	///
	/// String must be in the YYYY-MM-DD format.  It doesn't have to be
	/// zero-padded.
	explicit Date(const char* str) { convert(str); }
	
	/// \brief Initialize object from a C++ string containing a date


	///
	/// This works with any stringish class that declares a c_str()
	/// member function: std::string, mysqlpp::String...
	///
	/// \sa Date(const char*)
	template <class Str>
	explicit Date(const Str& str) { convert(str.c_str()); }

	/// \brief Initialize object from a \c time_t
	///
	/// Naturally, we throw away the "time" part of the \c time_t.  If
	/// you need to keep it, you want to use DateTime instead.
	explicit Date(time_t t);

	/// \brief Compare this date to another.
	///
	/// Returns < 0 if this date is before the other, 0 of they are
	/// equal, and > 0 if this date is after the other.
	int compare(const Date& other) const;

	/// \brief Parse a SQL date string into this object.
	const char* convert(const char*);

	/// \brief Get the date's day part, 1-31
	unsigned char day() const { return day_; }

	/// \brief Change the date's day part, 1-31
	void day(unsigned char d) { day_ = d; }

	/// \brief Get the date's month part, 1-12
	unsigned char month() const { return month_; }

	/// \brief Change the date's month part, 1-12
	void month(unsigned char m) { month_ = m; }

	/// \brief Convert to std::string
	operator std::string() const;

	/// \brief Convert to time_t
	///
	/// The "time" part of the \c time_t is "now"
	operator time_t() const;

	/// \brief Return our value in std::string form
	std::string str() const { return *this; }

	/// \brief Get the date's year part
	///
	/// There's no trickery here like in some date implementations
	/// where you have to add 1900 or something like that.
	unsigned short year() const { return year_; }

	/// \brief Change the date's year part
	///
	/// Pass the year value normally; we don't optimize the value by
	/// subtracting 1900 like some other date implementations.
	void year(unsigned short y) { year_ = y; }

private:
	unsigned short year_;	///< the year, as a simple integer, 1000-9999
	unsigned char month_;	///< the month, 1-12
	unsigned char day_;		///< the day, 1-31
};

/// \brief Inserts a Date object into a C++ stream
///
/// The format is YYYY-MM-DD, zero-padded.
///
/// \param os stream to insert date into
/// \param d date to insert into stream
MYSQLPP_EXPORT std::ostream& operator <<(std::ostream& os,
		const Date& d);


/// \brief C++ form of SQL's TIME type.
///
/// Objects of this class can be inserted into streams, and
/// initialized from SQL TIME strings.
class MYSQLPP_EXPORT Time : public Comparable<Time>
{
public:
	/// \brief Default constructor
	Time() : hour_(0), minute_(0), second_(0) { }

	/// \brief Initialize object
	/// \param h hour, 0-255 (yes, > 1 day is legal in SQL!)
	/// \param m minute, 0-59
	/// \param s second, 0-59
	Time(unsigned char h, unsigned char m, unsigned char s) :
	hour_(h),
	minute_(m),
	second_(s)
	{
	}

	/// \brief Initialize object as a copy of another Time
	Time(const Time& other) :
	Comparable<Time>(),
	hour_(other.hour_),
	minute_(other.minute_),
	second_(other.second_)
	{
	}

	/// \brief Initialize object from time part of date/time object
	Time(const DateTime& other) :
	Comparable<Time>(),
	hour_(other.hour()),
	minute_(other.minute()),
	second_(other.second())
	{
	}

	/// \brief Initialize object from a C string containing a SQL
	/// time string
	///



	/// String must be in the HH:MM:SS format.  It doesn't have to be

	/// zero-padded.
	explicit Time(const char* str) { convert(str); }



	/// \brief Initialize object from a C++ string containing a
	/// SQL time string
	///
	/// This works with any stringish class that declares a c_str()
	/// member function: std::string, mysqlpp::String...
	///
	/// \sa Time(const char*)
	template <class Str>
	explicit Time(const Str& str) { convert(str.c_str()); }

	/// \brief Initialize object from a \c time_t
	///
	/// Naturally, we throw away the "date" part of the \c time_t.  If
	/// you need to keep it, you want to use DateTime instead.
	explicit Time(time_t t);

	/// \brief Compare this time to another.
	///
	/// Returns < 0 if this time is before the other, 0 of they are
	/// equal, and > 0 if this time is after the other.
	int compare(const Time& other) const;

	/// \brief Parse a SQL time string into this object.
	const char* convert(const char*);

	/// \brief Get the time's hour part, 0-255
	unsigned char hour() const { return hour_; }

	/// \brief Change the time's hour part, 0-255
	void hour(unsigned char h) { hour_ = h; }

	/// \brief Get the time's minute part, 0-59
	unsigned char minute() const { return minute_; }

	/// \brief Change the time's minute part, 0-59
	void minute(unsigned char m) { minute_ = m; }

	/// Convert to std::string
	operator std::string() const;

	/// \brief Convert to time_t
	///
	/// The "date" part of the \c time_t is "today"
	operator time_t() const;

	/// \brief Get the time's second part, 0-59
	unsigned char second() const { return second_; }

	/// \brief Change the time's second part, 0-59
	void second(unsigned char s) { second_ = s; }

	/// Return our value in std::string form
	std::string str() const { return *this; }

private:
	unsigned char hour_;	///< the hour, 0-255 (yes, > 1 day is legal SQL!)
	unsigned char minute_;	///< the minute, 0-59
	unsigned char second_;	///< the second, 0-59
};

/// \brief Inserts a Time object into a C++ stream in a SQL-compatible
/// format.
///
/// The format is HH:MM:SS, zero-padded.
///
/// \param os stream to insert time into
/// \param t time to insert into stream
MYSQLPP_EXPORT std::ostream& operator <<(std::ostream& os,
		const Time& t);


} // end namespace mysqlpp

#endif // !defined(MYSQLPP_DATETIME_H)

|
|
|
>
>
>


<
|
>
|
|



















|
|



<
<
<
<
<


<
<
<
<
<
<
|
>
|
<
<
<
<
<
<
<
<
<
<
|
<
|
<
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
|
|
<
<
<
<
<
<
<
<
<
<
|
<
|
|
<

<
|
<
|
<
>
|
<
<
<
<
<
<
<
<
<
<
|
<
<
|
<
<
<
<
<
|
<
<
|
<
<
|
<
<
|
<
<

<
<
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<

<
<
|
<
|
|
<
|
|
<
<
|
|
<
|
<
<

|

>
>
|
<
|
<
|
<
<
<
<
<

<
<
<
<
<
<
<
|
<
<
<
<
<
<
<
<
<
<
<
|
<
<
|
>
|
|
<
<
|
|
<
<
<
|
<
<
<
<
<
|
<
<
<
<
<
<
<
<
<
<
<
<
|
<
|
<
<
<
<
|
<
<
<
<
<
<
<
<
<
<
<
|

<
|
<
|
<
>
>
|
<
<
|
<
<
<
|
<
<
<
<
<

|

<
<
<
|
|
<
|
<
<
|
|
<
|
<
<

<
<
<
<
<
<
|

<
<
|
<
<
|
<
<
<
<
<
|
<
|
<
<
|


<
|
|


<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
|
<
|
<
<
<
<
<
<
<
<
|
<
<
<
<
<
<
<
<
|
<
<
|
>
>
>
|
>
|
<
>
|
>
|
<
<
<
|
<
<
<
<
|
<
<
<
<
<
|
<
<
<
<
<

<
<
<
|
<
|
<
<

<
<
|
<
<
|
<
<

<
<
<
<
|
<
<
|
<
<
<
<
<
<
<
<
<
<


<
<
<
<
<
<
<
<
<
<
<


|
>
1
2
3
4
5
6
7
8

9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
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


56





57


58


59


60


61


62


















63


64

65
66

67
68


69
70

71


72
73
74
75
76
77

78

79





80







81











82


83
84
85
86


87
88



89





90












91

92




93











94
95

96

97

98
99
100


101



102





103
104
105



106
107

108


109
110

111


112






113
114


115


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





144



145

146


147


148


149


150




151


152










153
154











155
156
157
158
/// \file transaction.h
/// \brief Declares the Transaction class.
///
/// This object works with the Connection class to automate the use of
/// MySQL transactions.  It allows you to express these transactions
/// directly in C++ code instead of sending the raw SQL commands.

/***********************************************************************

 Copyright (c) 2006-2009 by Educational Technology Resources, Inc. and
 (c) 2008 by AboveNet, Inc.  Others may also hold copyrights on code
 in this file.  See the CREDITS.txt file in the top directory of the
 distribution for details.

 This file is part of MySQL++.

 MySQL++ is free software; you can redistribute it and/or modify it
 under the terms of the GNU Lesser General Public License as published
 by the Free Software Foundation; either version 2.1 of the License, or
 (at your option) any later version.

 MySQL++ is distributed in the hope that it will be useful, but WITHOUT
 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
 License for more details.

 You should have received a copy of the GNU Lesser General Public
 License along with MySQL++; if not, write to the Free Software
 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
 USA
***********************************************************************/

#if !defined(MYSQLPP_TRANSACTION_H)
#define MYSQLPP_TRANSACTION_H

#include "common.h"






namespace mysqlpp {







#if !defined(DOXYGEN_IGNORE)
// Make Doxygen ignore this
class MYSQLPP_EXPORT Connection;










#endif



/// \brief Helper object for creating exception-safe SQL transactions.




















class MYSQLPP_EXPORT Transaction










{

public:
	/// \brief Transaction isolation levels defined in SQL

	///

	/// These values can be passed to one of the Transaction

	/// constructors to change the way the database engine protects

	/// transactions from other DB updates.  These values are in order
	/// of increasing isolation, but decreasing performance.










	enum IsolationLevel {


		read_uncommitted,	///< allow "dirty reads" from other transactions





		read_committed,		///< only read rows committed by other transactions


		repeatable_read,	///< other transactions do not affect repeated reads in this transaction


		serializable		///< this transaction prevents writes to any rows it accesses while it runs


	};





	/// \brief Isolation level scopes defined in SQL


















	///


	/// These values are only used with one of the Transaction

	/// constructors, to select which transaction(s) our change to
	// the isolation scope will affect.

	enum IsolationScope {
		this_transaction,	///< change level for this transaction only


		session,			///< change level for all transactions in this session
		global				///< change level for all transactions on the DB server

	};



	/// \brief Simple constructor
	///
	/// \param conn The connection we use to manage the transaction set
	/// \param consistent Whether to use "consistent snapshots" during
	/// the transaction. See the documentation for "START TRANSACTION"

	/// in the MySQL manual for more on this.

	Transaction(Connection& conn, bool consistent = false);













	/// \brief Constructor allowing custom transaction isolation level











	/// and scope


	///
	/// \param conn The connection we use to manage the transaction set
	/// \param level Isolation level to use for this transaction
	/// \param scope Selects the scope of the isolation level change


	/// \param consistent Whether to use "consistent snapshots" during
	/// the transaction. See the documentation for "START TRANSACTION"



	/// in the MySQL manual for more on this.





	Transaction(Connection& conn, IsolationLevel level,












			IsolationScope scope = this_transaction,

			bool consistent = false);
















	/// \brief Destructor
	///

	/// If the transaction has not been committed or rolled back by the

	/// time the destructor is called, it is rolled back.  This is the

	/// right thing because one way this can happen is if the object is
	/// being destroyed as the stack is unwound to handle an exception.
	/// In that instance, you certainly want to roll back the


	/// transaction.



	~Transaction();






	/// \brief Commits the transaction
	///



	/// This commits all updates to the database using the connection
	/// we were created with since this object was created.  This is a

	/// no-op if the table isn't stored using a transaction-aware


	/// storage engine.  See CREATE TABLE in the MySQL manual for
	/// details.

	void commit();









	/// \brief Rolls back the transaction
	///


	/// This abandons all SQL statements made on the connection since


	/// this object was created.  This only works on tables stored using





	/// a transaction-aware storage engine.  See CREATE TABLE in the

	/// MySQL manual for details.


	void rollback();

private:

	Connection& conn_;	///! Connection to send queries through
	bool finished_;		///! True when we commit or roll back xaction
};































/// \brief Compile-time substitute for Transaction, which purposely








/// does nothing.  Use it to instantiate templates that take Transaction








/// when you don't want transactions to be used.


///
/// This was created for use with InsertPolicy, used by
/// Query::insertfrom().  You might use it when your code already
/// wraps a given sequence of MySQL++ calls in a transaction and does
/// an insertfrom() as part of that.  MySQL doesn't support nested
/// transactions, so you need to suppress the one insertfrom() would
/// normally start.

class MYSQLPP_EXPORT NoTransaction
{
public:
	/// \brief Constructor



	NoTransaction(Connection&, bool = false)




	{





	}









	/// \brief Destructor

	~NoTransaction() { }





	/// \brief stub to replace Transaction::commit()


	void commit() { }







	/// \brief stub to replace Transaction::rollback()


	void rollback() { }










};












} // end namespace mysqlpp

#endif // !defined(MYSQLPP_TRANSACTION_H)

Changes to lib/dbdriver.h.


1
2


3
4
5
6
7
8
9
10


11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
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
56
57




58
59




60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82

83
84
85
86
87

88
89



90
91
92
93
94
95
96
97
98
99
100
101
102






103
104
105

106
107
108
109
110
111
112
113
114
115
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
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
191
192
193

194
195
196
197
198
199
200
201
202
203

204
205
206
207
208
209
210
211
212


213
214
215
216
217

218


219
220
221
222
223
224
225
226

227
228

229
230
231
232
233
234
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



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
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
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
372
373
374
375
376
377
378
379
380
381
382
383
384

385


386
387
388
389


390
391
392
393

394
395
396
397

398
399

400
401
402
403


404
405
406
407
408
409
410
411



412
413

414
415
416

417
418
419
420
421
422

423
424
425
426
427
428
429


430
431


432
433
434
435

436
437
438
439

440
441
442
443
444
445


446
447
448
449
450
451
452

453
454
455
456
457
458
459
460
461
462
463
464


465
466
467
468

469
470
471
472
473
474
475
476


477
478



479
480
481
482
483

484
485
486
487
488
489
490
491
492
493
494
495
496
497


498
499
500
501
502
503

504
505

506
507
508
509
510
511
512
513
514
515
516
517
518
519



520
521
522
523
524
525
526
527
528

529
530
531
532
533
534





535
536
537
538
539
540
541
542
543
544




545
546
547
548
549

550
551
552
553
554
555
556
557
558
559
560
561
562
563



564
565
566
567
568
569
570


571
572
573
574
575
576

577
578
579
580

581


582
583
584
585
586
587
588

589
590



591
592
593
594
595
596
597
598
599
600
601
602
603
604
605

606
607
608


609
610
611
612
613
614




615
616
617
618
619
620
621
622
623
624
625
626





627



628




629
630
631


632
633
634
635
636

637
638
639
640
641

642

643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670

671


672




673







674
675
676
677
678
679
680
681
682
683




684







685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700



701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716

717
718

/// \file dbdriver.h
/// \brief Declares the DBDriver class.



/***********************************************************************
 Copyright (c) 1998 by Kevin Atkinson, (c) 1999-2001 by MySQL AB, and
 (c) 2004-2009 by Educational Technology Resources, Inc.  Others may
 also hold copyrights on code in this file.  See the CREDITS.txt file
 in the top directory of the distribution for details.

 This file is part of MySQL++.



 MySQL++ is free software; you can redistribute it and/or modify it
 under the terms of the GNU Lesser General Public License as published
 by the Free Software Foundation; either version 2.1 of the License, or
 (at your option) any later version.

 MySQL++ is distributed in the hope that it will be useful, but WITHOUT
 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
 License for more details.

 You should have received a copy of the GNU Lesser General Public
 License along with MySQL++; if not, write to the Free Software
 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
 USA
***********************************************************************/

#if !defined(MYSQLPP_DBDRIVER_H)
#define MYSQLPP_DBDRIVER_H

#include "common.h"



#include "options.h"

#include <typeinfo>

#include <limits.h>

namespace mysqlpp {

/// \brief Provides a thin abstraction layer over the underlying database 
/// client library.

///
/// This class does as little as possible to adapt between its public
/// interface and the interface required by the underlying C API.  That
/// is, in fact, its only mission.  The high-level interfaces indended
/// for use by MySQL++ users are in Connection, Query, Result, and
/// ResUse, all of which delegate the actual database communication to
/// an object of this type, created by Connection.  If you really need
/// access to the low-level database driver, get it via
/// Connection::driver(); don't create DBDriver objects directly.
///
/// Currently this is a concrete class for wrapping the MySQL C API.
/// In the future, it may be turned into an abstract base class, with
/// subclasses for different database server types.

class MYSQLPP_EXPORT DBDriver




{
public:




	/// \brief Result code returned by next_result()
	enum nr_code {
		nr_more_results,	///< success, with more results to come
		nr_last_result,		///< success, last result received
		nr_error,			///< problem retrieving next result
		nr_not_supported	///< this C API doesn't support "next result"
	};

	/// \brief Create object
	DBDriver();

	/// \brief Duplicate an existing driver
	///
	/// \param other existing DBDriver object
	///
	/// This establishes a new database server connection with the same
	/// parameters as the other driver's.
	DBDriver(const DBDriver& other);

	/// \brief Destroy object
	virtual ~DBDriver();

	/// \brief Return the number of rows affected by the last query

	///
	/// Wraps \c mysql_affected_rows() in the MySQL C API.
	ulonglong affected_rows()
	{
		error_message_.clear();

		return mysql_affected_rows(&mysql_);
	}




	/// \brief Get database client library version
	///
	/// Wraps \c mysql_get_client_info() in the MySQL C API.
	std::string client_version() const
	{
		error_message_.clear();
		return mysql_get_client_info();
	}

	/// \brief Establish a new connection using the same parameters as
	/// an existing connection.
	///






	/// \param mysql existing MySQL C API connection object
	bool connect(const MYSQL& mysql);


	/// \brief Connect to database server
	///
	/// If you call this method on an object that is already connected
	/// to a database server, the previous connection is dropped and a
	/// new connection is established.
	virtual bool connect(const char* host, const char* socket_name,
			unsigned int port, const char* db, const char* user,
			const char* password);

	/// \brief Return true if we have an active connection to the
	/// database server.
	///
	/// This does not actually check whether the connection is viable,

	/// it just indicates whether there was previously a successful
	/// connect() call and no disconnect().  Call ping() to actually
	/// test the connection's viability.

	bool connected() const { return is_connected_; }


	/// \brief Establish a new connection as a copy of an existing one
	///
	/// \param other the connection to copy
	void copy(const DBDriver& other);

	/// \brief Ask the database server to create a database
	///
	/// \param db name of database to create
	///

	/// \return true if database was created successfully
	bool create_db(const char* db) const;


	/// \brief Seeks to a particualr row within the result set
	///
	/// Wraps mysql_data_seek() in MySQL C API.
	void data_seek(MYSQL_RES* res, ulonglong offset) const
	{


		error_message_.clear();


		mysql_data_seek(res, offset);

	}

	/// \brief Drop the connection to the database server






	///
	/// This method should only be used by MySQL++ library internals.
	/// Unless you use the default constructor, this object should
	/// always be connected.
	void disconnect();

	/// \brief Drop a database
	///
	/// \param db name of database to destroy
	///
	/// \return true if database was created successfully
	bool drop_db(const std::string& db) const;



	/// \brief Enable SSL-encrypted connection.



	///
	/// \param key the pathname to the key file
	/// \param cert the pathname to the certificate file
	/// \param ca the pathname to the certificate authority file
	/// \param capath directory that contains trusted SSL CA
	///        certificates in pem format.
	/// \param cipher list of allowable ciphers to use
	///


	/// \return False if call fails or the C API library wasn't compiled
	/// with SSL support enabled.


	///
	/// Must be called before connection is established.
	///
	/// Wraps \c mysql_ssl_set() in MySQL C API.
	bool enable_ssl(const char* key = 0, const char* cert = 0,
			const char* ca = 0, const char* capath = 0,
			const char* cipher = 0);



	/// \brief Return error message for last MySQL error associated with
	/// this connection.

	///
	/// Can return a MySQL++ DBDriver-specific error message if there
	/// is one.  If not, it simply wraps \c mysql_error() in the MySQL C API.
	const char* error()
	{



		return error_message_.length() ? error_message_.c_str() : mysql_error(&mysql_);

	}

	/// \brief Return last MySQL error number associated with this
	/// connection
	///
	/// Wraps \c mysql_errno() in the MySQL C API.
	int errnum() { return mysql_errno(&mysql_); }


	/// \brief Return a SQL-escaped version of the given character
	/// buffer
	///
	/// \param to character buffer to hold escaped version; must
	/// point to at least (length * 2 + 1) bytes
	/// \param from pointer to the character buffer to escape
	/// \param length number of characters to escape
	///
	/// \retval number of characters placed in escaped
	///

	/// Wraps \c mysql_real_escape_string() in the MySQL C API.
	///
	/// Proper SQL escaping takes the database's current character set 
	/// into account, however if a database connection isn't available
	/// DBDriver also provides a static version of this same method.
	///
	/// \sa escape_string_no_conn(char*, const char*, size_t)
	size_t escape_string(char* to, const char* from, size_t length)
	{


		error_message_.clear();
		return mysql_real_escape_string(&mysql_, to, from, 
				static_cast<unsigned long>(length));
	}


	/// \brief Return a SQL-escaped version of a character buffer


	///
	/// \param ps pointer to C++ string to hold escaped version; if
	/// original is 0, also holds the original data to be escaped
	/// \param original if given, pointer to the character buffer to
	/// escape instead of contents of *ps
	/// \param length if both this and original are given, number of
	/// characters to escape instead of ps->length()
	///

	/// \retval number of characters placed in *ps
	///

	/// This method has three basic operation modes:
	///
	/// - Pass just a pointer to a C++ string containing the original
	///   data to escape, plus act as receptacle for escaped version
	/// - Pass a pointer to a C++ string to receive escaped string plus
	///   a pointer to a C string to be escaped
	/// - Pass nonzero for all parameters, taking original to be a
	///   pointer to an array of char with given length; does not treat
	///   null characters as special
	///
	/// There's a degenerate fourth mode, where ps is zero: simply



	/// returns 0, because there is nowhere to store the result.
	///
	/// Note that if original is 0, we always ignore the length
	/// parameter even if it is nonzero.  Length always comes from
	/// ps->length() in this case.
	///
	/// ps is a pointer because if it were a reference, the other
	/// overload would be impossible to call: the compiler would
	/// complain that the two overloads are ambiguous because
	/// std::string has a char* conversion ctor. A nice bonus is that
	/// pointer syntax makes it clearer that the first parameter is an
	/// "out" parameter.
	///
	/// \see comments for escape_string(char*, const char*, size_t)
	/// for further details.
	/// 
	/// \sa escape_string_no_conn(std::string*, const char*, size_t)
	size_t escape_string(std::string* ps, const char* original,
			size_t length);

	/// \brief SQL-escapes the given string without reference to the 
	/// character set of a database server.




	///
	/// Wraps \c mysql_escape_string() in the MySQL C API.
	///
	/// \sa escape_string(char*, const char*, size_t)
	static size_t escape_string_no_conn(char* to, const char* from,
			size_t length)
	{



		return mysql_escape_string(to, from,




				static_cast<unsigned long>(length));
	}


	/// \brief SQL-escapes the given string without reference to the 
	/// character set of a database server.
	///
	/// \sa escape_string(std::string*, const char*, size_t),
	/// escape_string_no_conn(char*, const char*, size_t)
	static size_t escape_string_no_conn(std::string* ps, 
			const char* original = 0, size_t length = 0);

	/// \brief Executes the given query string
	///
	/// Wraps \c mysql_real_query() in the MySQL C API.
	bool execute(const char* qstr, size_t length)
	{
		error_message_.clear();
		return !mysql_real_query(&mysql_, qstr,
				static_cast<unsigned long>(length));
	}

	/// \brief Returns the next raw C API row structure from the given
	/// result set.
	///
	/// This is for "use" query result sets only.  "store" queries have
	/// all the rows already.
	///
	/// Wraps \c mysql_fetch_row() in MySQL C API.
	MYSQL_ROW fetch_row(MYSQL_RES* res) const
	{







		error_message_.clear();
		return mysql_fetch_row(res);
	}


	/// \brief Returns the lengths of the fields in the current row
	/// from a "use" query.
	///
	/// Wraps \c mysql_fetch_lengths() in MySQL C API.
	const unsigned long* fetch_lengths(MYSQL_RES* res) const
	{

		error_message_.clear();
		return mysql_fetch_lengths(res);
	}


	/// \brief Returns information about a particular field in a result






	/// set




	///
	/// \param res result set to fetch field information for
	/// \param i field number to fetch information for, if given
	///
	/// If i parameter is given, this call is like a combination of
	/// field_seek() followed by fetch_field() without the i parameter,
	/// which otherwise just iterates through the set of fields in the
	/// given result set.
	///
	/// Wraps \c mysql_fetch_field() and mysql_fetch_field_direct() in
	/// MySQL C API.  (Which one it uses depends on i parameter.)
	MYSQL_FIELD* fetch_field(MYSQL_RES* res, size_t i = UINT_MAX) const
	{

		error_message_.clear();
		return i == UINT_MAX ? mysql_fetch_field(res) :
				mysql_fetch_field_direct(res,
				static_cast<unsigned int>(i));
	}

	/// \brief Jumps to the given field within the result set
	///
	/// Wraps \c mysql_field_seek() in MySQL C API.


	void field_seek(MYSQL_RES* res, size_t field) const
	{
		error_message_.clear();
		mysql_field_seek(res, MYSQL_FIELD_OFFSET(field));
	}


	/// \brief Releases memory used by a result set
	///
	/// Wraps \c mysql_free_result() in MySQL C API.
	void free_result(MYSQL_RES* res) const
	{

		error_message_.clear();
		mysql_free_result(res);
	}

	/// \brief Return the connection options object
	st_mysql_options get_options() const { return mysql_.options; }

	/// \brief Get information about the IPC connection to the
	/// database server

	///
	/// String contains info about type of connection (e.g. TCP/IP,

	/// named pipe, Unix socket...) and the server hostname.
	///
	/// Wraps \c mysql_get_host_info() in the MySQL C API.
	std::string ipc_info()
	{




		error_message_.clear();
		return mysql_get_host_info(&mysql_);

	}

	/// \brief Get ID generated for an AUTO_INCREMENT column in the
	/// previous INSERT query.


	///
	/// \retval 0 if the previous query did not generate an ID.  Use
	/// the SQL function LAST_INSERT_ID() if you need the last ID
	/// generated by any query, not just the previous one.  This
	/// applies to stored procedure calls because this function returns
	/// the ID generated by the last query, which was a CALL statement,
	/// and CALL doesn't generate IDs.  You need to use LAST_INSERT_ID()
	/// to get the ID in this case.
	ulonglong insert_id()
	{
		error_message_.clear();
		return mysql_insert_id(&mysql_);
	}


	/// \brief Kill a MySQL server thread


	///
	/// \param tid ID of thread to kill
	///
	/// Wraps \c mysql_kill() in the MySQL C API.


	///
	/// \see thread_id()
	bool kill(unsigned long tid)
	{

		error_message_.clear();
		return !mysql_kill(&mysql_, tid);
	}


	/// \brief Returns true if there are unconsumed results from the
	/// most recent query.

	///
	/// Wraps \c mysql_more_results() in the MySQL C API.
	bool more_results()
	{


		error_message_.clear();
		#if MYSQL_VERSION_ID > 41000		// only in MySQL v4.1 +
			return mysql_more_results(&mysql_);
		#else
			return false;
		#endif
	}




	/// \brief Moves to the next result set from a multi-query
	///

	/// \return A code indicating whether we successfully found another
	/// result, there were no more results (but still success) or
	/// encountered an error trying to find the next result set.

	///
	/// Wraps \c mysql_next_result() in the MySQL C API, with
	/// translation of its return value from magic integers to nr_code
	/// enum values.
	nr_code next_result()
	{

		error_message_.clear();
		#if MYSQL_VERSION_ID > 41000		// only in MySQL v4.1 +
			switch (mysql_next_result(&mysql_)) {
				case 0:  return nr_more_results;
				case -1: return nr_last_result;
				default: return nr_error;
			}


		#else
			return nr_not_supported;


		#endif
	}

	/// \brief Returns the number of fields in the given result set

	///
	/// Wraps \c mysql_num_fields() in MySQL C API.
	int num_fields(MYSQL_RES* res) const
	{

		error_message_.clear();
		return mysql_num_fields(res);
	}

	/// \brief Returns the number of rows in the given result set
	///


	/// Wraps \c mysql_num_rows() in MySQL C API.
	ulonglong num_rows(MYSQL_RES* res) const
	{
		error_message_.clear();
		return mysql_num_rows(res);
	}


	/// \brief "Pings" the MySQL database
	///
	/// This function will try to reconnect to the server if the 
	/// connection has been dropped.  Wraps \c mysql_ping() in the MySQL C API.
	/// 
	/// \retval true if server is responding, regardless of whether we had
	/// to reconnect or not
	/// \retval false if either we already know the connection is down
	/// and cannot re-establish it, or if the server did not respond to
	/// the ping and we could not re-establish the connection.
	bool ping()
	{


		error_message_.clear();
		return !mysql_ping(&mysql_);
	}


	/// \brief Returns version number of MySQL protocol this connection
	/// is using
	///
	/// Wraps \c mysql_get_proto_info() in the MySQL C API.
	int protocol_version()
	{
		error_message_.clear();
		return mysql_get_proto_info(&mysql_);


	}




	/// \brief Returns information about the last executed query
	///
	/// Wraps \c mysql_info() in the MySQL C API
	std::string query_info();


	/// \brief Asks the database server to refresh certain internal data
	/// structures.
	///
	/// Wraps \c mysql_refresh() in the MySQL C API.  There is no
	/// corresponding interface for this in higher level MySQL++ classes
	/// because it was undocumented until recently, and it's a pretty
	/// low-level thing.  It's designed for things like MySQL
	/// Administrator.
	bool refresh(unsigned options)
	{
		error_message_.clear();
		return !mysql_refresh(&mysql_, options);
	}



	/// \brief Returns true if the most recent result set was empty
	///
	/// Wraps \c mysql_field_count() in the MySQL C API, returning true
	/// if it returns 0.
	bool result_empty()
	{

		error_message_.clear();
		return mysql_field_count(&mysql_) == 0;

	}

	/// \brief Asks the database server to switch to a different database
	bool select_db(const char* db)
	{
		error_message_.clear();
		return !mysql_select_db(&mysql_, db);
	}

	/// \brief Get the database server's version number
	///
	/// Wraps \c mysql_get_server_info() in the MySQL C API.
	std::string server_version()
	{



		error_message_.clear();
		return mysql_get_server_info(&mysql_);
	}

	/// \brief Sets a connection option
	///
	/// This is the database-independent high-level option setting
	/// interface that Connection::set_option() calls.  There are
	/// several private overloads that actually implement the option

	/// setting.
	///
	/// \see Connection::set_option(Option*) for commentary
	bool set_option(Option* o);

	/// \brief Set MySQL C API connection option





	///
	/// \internal Wraps \c mysql_options() in C API.
	bool set_option(mysql_option moption, const void* arg = 0)
	{
		error_message_.clear();
		return !mysql_options(&mysql_, moption,
				static_cast<const char*>(arg));
	}

	#if MYSQL_VERSION_ID >= 40101




	/// \brief Set MySQL C API connection option
	///
	/// \internal Wraps \c mysql_set_server_option() in C API.
	bool set_option(enum_mysql_set_option msoption)
	{

		error_message_.clear();
		return !mysql_set_server_option(&mysql_, msoption);
	}
	#endif

	/// \brief Set MySQL C API connection option
	///
	/// Manipulates the MYSQL.client_flag bit mask.  This allows these
	/// flags to be treated the same way as any other connection option,
	/// even though the C API handles them differently.
	bool set_option(unsigned int option, bool arg);

	/// \brief Same as set_option(), except that it won't override
	/// a previously-set option.



	bool set_option_default(Option* o)
	{
		const std::type_info& ti = typeid(o);
		for (OptionList::const_iterator it = applied_options_.begin();
				it != applied_options_.end();
				++it) {
			if (typeid(*it) == ti) {


				delete o;
				return "";		// option of this type already set
			}
		}

		return set_option(o);

	}

	/// \brief Ask database server to shut down.
	///

	/// User must have the "shutdown" privilege.


	///
	/// Wraps \c mysql_shutdown() in the MySQL C API.
	bool shutdown();

	/// \brief Returns the database server's status
	///
	/// String is similar to that returned by the \c mysqladmin

	/// \c status command.  Among other things, it contains uptime 
	/// in seconds, and the number of running threads, questions



	/// and open tables.
	///
	/// Wraps \c mysql_stat() in the MySQL C API.
	std::string server_status()
	{
		error_message_.clear();
		return mysql_stat(&mysql_);
	}

	/// \brief Saves the results of the query just execute()d in memory
	/// and returns a pointer to the MySQL C API data structure the
	/// results are stored in.
	///
	/// \sa use_result()
	///

	/// Wraps \c mysql_store_result() in the MySQL C API.
	MYSQL_RES* store_result()
	{


		error_message_.clear();
		return mysql_store_result(&mysql_);
	}

	/// \brief Returns true if MySQL++ and the underlying MySQL C API
	/// library were both compiled with thread awareness.




	///
	/// This is based in part on a MySQL C API function
	/// mysql_thread_safe().  We deliberately don't call this wrapper
	/// thread_safe() because it's a misleading name: linking to
	/// thread-aware versions of the MySQL++ and C API libraries doesn't
	/// automatically make your program "thread-safe".  See the
	/// <a href="../userman/threads.html">chapter on threads</a> in the
	/// user manual for more information and guidance.
	static bool thread_aware();

	/// \brief Tells the underlying MySQL C API library that this thread
	/// is done using the library.





	///



	/// This exists because the MySQL C API library allocates some per-thread




	/// memory which it doesn't release until you call this.
	static void thread_end()
	{


		#if MYSQL_VERSION_ID > 40000		// only in MySQL v4.0 +
			mysql_thread_end();
		#endif
	}


	/// \brief Returns the MySQL server thread ID for this connection
	///
	/// This has nothing to do with threading on the client side. It's
	/// a server-side thread ID, to be used with kill().
	unsigned long thread_id()

	{

		error_message_.clear();
		return mysql_thread_id(&mysql_);
	}

	/// \brief Tells the underlying C API library that the current
	/// thread will be using the library's services.
	///
	/// \retval True if there was no problem
	///
	/// The MySQL++ user manual's <a href="../userman/threads.html">chapter
	/// on threads</a> details two major strategies for dealing with
	/// connections in the face of threads.  If you take the simpler
	/// path, creating one DBDriver object per thread, it is never
	/// necessary to call this function; the underlying C API will call it
	/// for you when you establish the first database server connection
	/// from that thread.  If you use a more complex connection
	/// management strategy where it's possible for one thread to
	/// establish a connection that another thread uses, you must call
	/// this from each thread that can use the database before it creates
	/// any MySQL++ objects.  If you use a DBDriverPool object, this
	/// applies; DBDriverPool isn't smart enough to call this for you,
	/// and the MySQL C API won't do it, either.
	static bool thread_start()
	{
		#if MYSQL_VERSION_ID > 40000		// only in MySQL v4.0 +
			return !mysql_thread_init();
		#else
			return false;

		#endif


	}












	/// \brief Returns a result set from the last-executed query which
	/// we can walk through in linear fashion, which doesn't store all
	/// result sets in memory.
	///
	/// \sa store_result
	///
	/// Wraps \c mysql_use_result() in the MySQL C API.
	MYSQL_RES* use_result()
	{
		error_message_.clear();




		return mysql_use_result(&mysql_);







	}

protected:
	/// \brief Does things common to both connect() overloads, before
	/// each go and establish the connection in their different ways.
	bool connect_prepare();

	/// \brief Common implementation of set_option(Option*) and the
	/// delayed option setting code in connect_prepare()
	bool set_option_impl(Option* o);

private:
	/// \brief Data type of the list of applied connection options
	typedef std::deque<Option*> OptionList;

	/// \brief Iterator into an OptionList



	typedef OptionList::iterator OptionListIt;

	/// \brief Hidden assignment operator; we don't want to be copied
	/// that way.  What would it mean?
	DBDriver& operator=(const DBDriver&);

	MYSQL mysql_;
	bool is_connected_;
	OptionList applied_options_;
	OptionList pending_options_;
	mutable std::string error_message_;
};


} // end namespace mysqlpp


#endif // !defined(MYSQLPP_DBDRIVER_H)

>
|
|
>
>

<
<
<
|
|

|
>
>

<
<
|
|
|
|
|
<
<
|
<
<
<
<
<
|
<
<
|
<
|
>
>
|
|
|
|
<

<
|
<
<
>
|
<
|
|
|
|
<
<
<
|
<
<
<
|
<
>
>
>
>
|
<
>
>
>
>
|
|
<
<
<
<
<

|
|
|
|
|
<
<
<
<
<

<
<
|
<
>
|
<
<
|
<
>
|
<
>
>
>

|
|
<
<
<
<
<
<
|
<
|
|
>
>
>
>
>
>
|
|
|
>
|
|
|
|
|
|
<
<
|
|
|
<
|
>
|
|
|
>
|
>

<
<
|
|

|
|
|
|
>
|
|
>
|
|
|
<
<
|
>
>
|
>
>
|
>
|
|
<
>
>
>
>
>
>
|
<
<
<
<

<
<
<
<
<
|
>
>

<
>
>
>
|
|
<
<
|
<
|
|
>
>
|
<
>
>
|
<
|
<
<
<
<

>
>
|
|
>
<
<
<
<
|
>
>
>
|
>
|
|
|
|
|
|
<

>
|
|
|
|
|
<
<
|
|
<
>
|
|
|
|
|
|
<
<
|
>
>
|
|
<
|
|
>
|
>
>
|
<
<
<
<
<
|
<
>
|
<
>
|
|
|
|
|
|
<
<
<
|
|
>
>
>
|
|
|
<
<
|
<
|
|
|
|
|
|
<
<
|
<
<
<

<
<
>
>
>
>
|
<
|
<
<
<
|
>
>
>
|
>
>
>
>
<
|
|
>
|
|
|
|
<
<
<
|
<
|
<
<
<
<
<
<
<
|
<
<
<
<
<
<
<
<
|
>
>
>
>
>
>
>
|
|
<
|
>
|
|
|
|
|
<
>
|
|
<
|
>
|
>
>
>
>
>
>
|
>
>
>
>
|
<
<
|
<
<
|
|
|
|
|
|
<
>
|
|
|
<
<
|
<
<
|
>
>
|
<
<
|
<
|
>
|
|
|
|
<
>
|
|
<
|
<
<
|
<
<
>
|
<
>
<
<
<
<
|
>
>
>
>
|
|
>
|
|
<
|
>
>
|
<
<
<
<
<
<
<
<
<
<
<
|
|
>
|
>
>
|
<
|
<
>
>
|
<
<
<
>
|
|
<
|
>
|
|
>
|
<
|
<
>
>
|
<
<
|
<
|
<
|
>
>
>
|
|
>
|
|
|
>
|
<
|
|
|
<
>
|
<
<
|
|
|
<
>
>
|
<
>
>
|
<
|
<
>
|
<
|
<
>
|
|
<
|
<
|
>
>
|
|
<
|
|
<
|
>
|
|
|
|
|
|
|
|
|
|
<
<
>
>
|
|
<
|
>
|
|
<
<
<
|
<
<
>
>
|
|
>
>
>
|
|
|
<

>
|
|
|
|
|
|
|
<
<
<
<
<
|
|
>
>
|
|
|
|
|
<
>
|
|
>
|
|
<
|
<
<
<
<
|
|
<
<
<
|
>
>
>
|
<
|
|
<
|
<
<
<
>
|
<
<
|

|
>
>
>
>
>
|
|
<
<
<
<
<
|
|
<
>
>
>
>
|
|
<
|
|
>
|
|
<
|
|
<
|
<
<
<
|

<
|
>
>
>
|
|
<
<
|
|
|
>
>
|
<
<
<
|
|
>
|
|
|
<
>
|
>
>
|
<
<

<
<
<
>
|
|
>
>
>
|
<
<
<
|
<
<
<
|
<
<
<
<
<
<
>
<
<
|
>
>
|
|
<
|
<
|
>
>
>
>
|
<
<
|
<
<
|
|
<
|
<
|
>
>
>
>
>
|
>
>
>
|
>
>
>
>
<
<
|
>
>
|
|
|
<
|
>
|
|
<
<
|
>
|
>
|
<
<
|
<
<
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
|
<
<
<
<
>
|
>
>
|
>
>
>
>

>
>
>
>
>
>
>
<
<
<
<
<
<
<
<
|
<
>
>
>
>
|
>
>
>
>
>
>
>
|
|
<
<
|
|
|
|
<
<
|
<
<
<

|
>
>
>
|
|
|
|
|

|
|
|
|
|
<
|
|
|
|
>
|
|
1
2
3
4
5
6



7
8
9
10
11
12
13


14
15
16
17
18


19





20


21

22
23
24
25
26
27
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





56


57

58
59


60

61
62

63
64
65
66
67
68






69

70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87


88
89
90

91
92
93
94
95
96
97
98
99


100
101
102
103
104
105
106
107
108
109
110
111
112
113


114
115
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
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
191
192
193
194
195
196





197

198
199

200
201
202
203
204
205
206



207
208
209
210
211
212
213
214


215

216
217
218
219
220
221


222



223


224
225
226
227
228

229



230
231
232
233
234
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

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


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

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


372
373
374

375
376
377

378
379
380

381

382
383

384

385
386
387

388

389
390
391
392
393

394
395

396
397
398
399
400
401
402
403
404
405
406
407


408
409
410
411

412
413
414
415



416


417
418
419
420
421
422
423
424
425
426

427
428
429
430
431
432
433
434
435





436
437
438
439
440
441
442
443
444

445
446
447
448
449
450

451




452
453



454
455
456
457
458

459
460

461



462
463


464
465
466
467
468
469
470
471
472
473





474
475

476
477
478
479
480
481

482
483
484
485
486

487
488

489



490
491

492
493
494
495
496
497


498
499
500
501
502
503



504
505
506
507
508
509

510
511
512
513
514


515



516
517
518
519
520
521
522



523



524






525


526
527
528
529
530

531

532
533
534
535
536
537


538


539
540

541

542
543
544
545
546
547
548
549
550
551
552
553
554
555
556


557
558
559
560
561
562

563
564
565
566


567
568
569
570
571


572


573
















574




575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591








592

593
594
595
596
597
598
599
600
601
602
603
604
605
606


607
608
609
610


611



612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627

628
629
630
631
632
633
634
<?xml version="1.0"?>
<makefile>
  <requires version="0.2.9"/>
  <using module="datafiles"/>
  <include file="presets/simple.bkl"/>




  <set var="DDD">$(DOLLAR)$(DOLLAR)d</set>
  <set var="DDF">$(DOLLAR)$(DOLLAR)f</set>

  <set var="STABLEABI">3.1.0</set>
  <set var="OLDABIDIR">../$(STABLEABI)/abi_dumps/mysqlpp</set>
  <set var="NEWABIDIR">./abi_dumps/mysqlpp</set>



  <set var="PLATFORM_WINDOWS_NATIVE">no</set>
  <set var="THREAD_TYPE">single</set>
  <if cond="FORMAT in ['msvs2003prj', 'msvs2005prj', 'msvs2008prj', 'mingw']">
    <set var="PLATFORM_WINDOWS_NATIVE">yes</set>
    <set var="THREAD_TYPE">multi</set>


  </if>





    


  <option name="BUILD">

    <values>debug,release</values>
    <values-description>Debug,Release</values-description>
    <default-value>debug</default-value>
    <description>
      Type of compiled binaries
    </description>
  </option>



  <set var="MYSQL_WIN_DIR">


    C:\Program Files\MySQL\MySQL Connector C 6.1
  </set>


  <set var="DEBUGINFO">
    <if cond="BUILD=='debug'">on</if>
    <if cond="BUILD=='release'">off</if>



  </set>



  

  <set var="OPTIMIZE_FLAG">
    <if cond="BUILD=='debug'">off</if>
    <if cond="BUILD=='release'">speed</if>
  </set>


  <!-- This convoluted syntax adds "_d" to the end of library and DLL
     file names for VC++ and Xcode, in debug mode only. -->
  <set var="DEBUG_SUFFIX"/>
  <set var="DEBUG_SUFFIX">
    <if cond="FORMAT in ['msvs2003prj', 'msvs2005prj', 'msvs2008prj', 'xcode2'] and BUILD=='debug'">_d</if>
  </set>






  <set var="BUILDDOCS">yes</set>
  <set var="BUILDEXAMPLES">yes</set>
  <set var="BUILDLIBRARY">yes</set>
  <set var="BUILDTEST">yes</set>
  <set var="HEADER_DIR">$(PREFIX)/include/mysql++</set>








  <if cond="FORMAT in ['msvs2003prj', 'msvs2005prj', 'msvs2008prj']">

    <set-srcdir>..</set-srcdir>
  </if>




  <if cond="BUILDLIBRARY=='yes'">
    <dll id="mysqlpp">

      <dllname>mysqlpp$(DEBUG_SUFFIX)</dllname>
      <libname>mysqlpp$(DEBUG_SUFFIX)</libname>
      <so_version>3.2.0</so_version>

      <sources>
        lib/beemutex.cpp






        lib/cmdline.cpp

        lib/connection.cpp
        lib/cpool.cpp
        lib/datetime.cpp
        lib/dbdriver.cpp
        lib/field_names.cpp
        lib/field_types.cpp
        lib/manip.cpp
        lib/myset.cpp
        lib/mysql++.cpp
        lib/mystring.cpp
        lib/null.cpp
        lib/options.cpp
        lib/qparms.cpp
        lib/query.cpp
        lib/result.cpp
        lib/row.cpp
        lib/scopedconnection.cpp
        lib/sql_buffer.cpp


        lib/sqlstream.cpp
        lib/ssqls2.cpp
        lib/stadapter.cpp

        lib/tcp_connection.cpp
        lib/transaction.cpp
        lib/type_info.cpp
        lib/uds_connection.cpp
        lib/utility.cpp
        lib/vallist.cpp
        lib/wnp_connection.cpp
      </sources>



      <debug-info>$(DEBUGINFO)</debug-info>
      <optimize>$(OPTIMIZE_FLAG)</optimize>

      <threading>$(THREAD_TYPE)</threading>
      <cxx-rtti>on</cxx-rtti>
      <cxx-exceptions>on</cxx-exceptions>
      
      <install-to>$(LIBDIR)</install-to>
      
      <if cond="PLATFORM_WINDOWS_NATIVE=='yes'">
        <define>UNICODE</define>
        <define>_UNICODE</define>
        <sys-lib>wsock32</sys-lib>
      </if>



      <if cond="FORMAT in ['msvs2003prj', 'msvs2005prj', 'msvs2008prj']">
        <define>MYSQLPP_MAKING_DLL</define>
        <define>HAVE_MYSQL_SSL_SET</define>
        <include>$(MYSQL_WIN_DIR)\include</include>
        <lib-path>$(MYSQL_WIN_DIR)\lib\opt</lib-path>
        <sys-lib>libmysql</sys-lib>
      </if>

      <if cond="FORMAT=='mingw'">

        <define>MYSQLPP_NO_DLL</define>
        <define>HAVE_MYSQL_SSL_SET</define>
        <include>"$(MYSQL_WIN_DIR)\include"</include>
        <ldflags>-Wl,--enable-stdcall-fixup</ldflags>
        <lib-path>"$(MYSQL_WIN_DIR)\lib\opt"</lib-path>
        <sys-lib>mysql</sys-lib>
      </if>










      <if cond="FORMAT=='autoconf'">
        <depends>lib/ssqls.h</depends>
        <depends>lib/querydef.h</depends>


        <cxxflags>@PTHREAD_CFLAGS@</cxxflags>
        <include>.</include>
        <ldflags>-l@MYSQL_C_LIB_NAME@ @PTHREAD_LIBS@ @MYSQLPP_EXTRA_LIBS@</ldflags>
      </if>



      <if cond="FORMAT=='xcode2'">

        <define>HAVE_POSIX_GETOPT</define>
        <define>MYSQLPP_XCODE</define>
        <include>/usr/local/mysql/include</include>
        <ldflags>-lmysqlclient</ldflags>
        <!-- Assume C API files came from MySQL.com DMGs, not source

             tarball, Fink, etc., inferring preference from use of Xcode. -->
        <lib-path>/usr/local/mysql/lib</lib-path>
      </if>

    </dll>





    <data-files>
      <files>lib/*.h</files>
      <install-to>$(HEADER_DIR)</install-to>
    </data-files>
  </if>   <!-- build library -->





  <!-- Set up build options common to all built executables -->
  <template id="programs">
    <if cond="BUILDLIBRARY=='yes'">
      <depends>mysqlpp</depends>
    </if>

    <threading>$(THREAD_TYPE)</threading>
    <cxx-rtti>on</cxx-rtti>
    <cxx-exceptions>on</cxx-exceptions>
    <debug-info>$(DEBUGINFO)</debug-info>
    <optimize>$(OPTIMIZE_FLAG)</optimize>


    <if cond="FORMAT in ['autoconf', 'gnu', 'mingw', 'xcode2']">
      <include>lib</include>
      <lib-path>.</lib-path>
    </if>
    <if cond="FORMAT in ['msvs2003prj', 'msvs2005prj', 'msvs2008prj']">
      <include>../lib</include>


    </if>


    <if cond="FORMAT=='xcode2'">
      <define>HAVE_POSIX_GETOPT</define>
      <define>MYSQLPP_XCODE</define>
      <include>/usr/local/mysql/include</include>
      <ldflags>-lmysqlclient</ldflags>
      <lib-path>/usr/local/mysql/lib</lib-path>
    </if>



    <if cond="PLATFORM_WINDOWS_NATIVE=='yes'">
      <define>UNICODE</define>
      <define>_UNICODE</define>
    </if>


    <if cond="FORMAT=='autoconf'">
      <cxxflags>@PTHREAD_CFLAGS@</cxxflags>
      <ldflags>-l@MYSQL_C_LIB_NAME@ @PTHREAD_LIBS@ @MYSQLPP_EXTRA_LIBS@</ldflags>
      <warnings>max</warnings>
      <sys-lib>mysqlpp</sys-lib>
    </if>







    <if cond="FORMAT=='mingw'">
      <define>MYSQLPP_NO_DLL</define>

      <ldflags>
        -Wl,--enable-auto-import -Wl,--enable-runtime-pseudo-reloc -Wl,--enable-stdcall-fixup
      </ldflags>
      <include>"$(MYSQL_WIN_DIR)\include"</include>
      <lib-path>"$(MYSQL_WIN_DIR)\lib\opt"</lib-path>
      <sys-lib>mysql</sys-lib>
      <sys-lib>mysqlpp$(DEBUG_SUFFIX)</sys-lib>



    </if>

    <if cond="FORMAT in ['msvs2003prj', 'msvs2005prj', 'msvs2008prj']">
      <lib-path>$(BUILD)</lib-path>
      <include>$(MYSQL_WIN_DIR)\include</include>
      <lib-path>$(MYSQL_WIN_DIR)\lib\opt</lib-path>
      <sys-lib>mysqlpp$(DEBUG_SUFFIX)</sys-lib>
      <sys-lib>libmysql</sys-lib>


    </if>


    <if cond="FORMAT=='gnu'">
      <include>/usr/include/mysql</include>
      <include>/usr/include/mysql++</include>
      <sys-lib>mysqlpp</sys-lib>
      <sys-lib>mysqlclient</sys-lib>


    </if>






    <if cond="FORMAT=='xcode2'">
      <include>/usr/local/mysql/include</include>
      <sys-lib>mysqlclient</sys-lib>
      <sys-lib>mysqlpp$(DEBUG_SUFFIX)</sys-lib>
    </if>

  </template>




  <if cond="BUILDLIBRARY=='yes'">
    <!-- SSQLS v2 parser convenience library -->
    <lib id="ssqls2parse" template="programs">
      <depends>mysqlpp</depends>
      <libname>mysqlpp_ssqls2parse</libname>
      <sources>ssx/parsev2.cpp</sources>
      <include>.</include>
    </lib>


    <!-- Build rules for ssqlsxlat tool -->
    <exe id="ssqlsxlat" template="programs">
      <sources>ssx/genv2.cpp</sources>
      <sources>ssx/main.cpp</sources>
      <depends>ssqls2parse</depends>
      <sys-lib>mysqlpp_ssqls2parse</sys-lib>



      <sys-lib>mysqlpp</sys-lib>

    </exe>







  </if>









  <!-- Define library testing programs' output targets, if enabled -->
  <if cond="BUILDTEST=='yes'">
    <exe id="test_array_index" template="programs">
      <sources>test/array_index.cpp</sources>
    </exe>
    <exe id="test_cpool" template="programs">
      <sources>test/cpool.cpp</sources>
    </exe>
    <exe id="test_datetime" template="programs">

      <sources>test/datetime.cpp</sources>
    </exe>
    <exe id="test_inttypes" template="programs">
      <sources>test/inttypes.cpp</sources>
    </exe>
    <exe id="test_insertpolicy" template="programs">
      <sources>test/insertpolicy.cpp</sources>

    </exe>
    <exe id="test_manip" template="programs">
      <sources>test/manip.cpp</sources>

    </exe>
    <if cond="FORMAT!='msvs2003prj'">
      <!-- VC++ 2003 can't compile this -->
      <exe id="test_null_comparison" template="programs">
        <sources>test/null_comparison.cpp</sources>
      </exe>
    </if>
    <exe id="test_query_copy" template="programs">
      <sources>test/query_copy.cpp</sources>
    </exe>
    <if cond="FORMAT!='msvs2003prj'">
      <!-- VC++ 2003 can't compile this -->
      <exe id="test_qssqls" template="programs">
        <sources>test/qssqls.cpp</sources>
      </exe>


    </if>


    <exe id="test_qstream" template="programs">
      <sources>test/qstream.cpp</sources>
    </exe>
    <exe id="test_sqlstream" template="programs">
      <sources>test/sqlstream.cpp</sources>
    </exe>

    <if cond="BUILDLIBRARY=='yes'">
      <exe id="test_ssqls2" template="programs">
        <sources>test/ssqls2.cpp</sources>
        <depends>ssqls2parse</depends>


        <sys-lib>mysqlpp_ssqls2parse</sys-lib>


        <sys-lib>mysqlpp</sys-lib>
      </exe>
    </if>
    <if cond="FORMAT!='msvs2003prj'">


      <!-- VC++ 2003 can't compile this -->

      <exe id="test_string" template="programs">
        <sources>test/string.cpp</sources>
      </exe>
    </if>
    <exe id="test_tcp" template="programs">
      <sources>test/tcp.cpp</sources>

    </exe>
    <exe id="test_uds" template="programs">
      <sources>test/uds.cpp</sources>

    </exe>


    <exe id="test_wnp" template="programs">


      <sources>test/wnp.cpp</sources>
    </exe>

  </if>   <!-- build library test programs -->





  <!-- Define example programs' output targets, if enabled -->
  <if cond="BUILDEXAMPLES=='yes'">
    <!-- Options specific to examples that depend on libexcommon -->
    <template id="libexcommon-user">
      <depends>excommon</depends>
      <sys-lib>mysqlpp_excommon</sys-lib>
    </template>

    <!-- Convenience library of routines used by most examples -->

    <lib id="excommon" template="programs">
      <libname>mysqlpp_excommon</libname>
      <sources>examples/printdata.cpp</sources>
    </lib>












    <!-- The examples themselves -->
    <if cond="FORMAT!='msvs2003prj'">
      <!-- VC++ 2003 can't compile current SSQLS code -->
      <exe id="cgi_jpeg" template="libexcommon-user,programs">
        <sources>examples/cgi_jpeg.cpp</sources>
      </exe>

    </if>

    <exe id="cpool" template="libexcommon-user,programs">
      <sources>examples/cpool.cpp</sources>
    </exe>



    <exe id="dbinfo" template="libexcommon-user,programs">
      <sources>examples/dbinfo.cpp</sources>
    </exe>

    <exe id="deadlock" template="libexcommon-user,programs">
      <sources>examples/deadlock.cpp</sources>
    </exe>
    <exe id="fieldinf" template="libexcommon-user,programs">
      <sources>examples/fieldinf.cpp</sources>
    </exe>

    <if cond="FORMAT!='msvs2003prj'">

      <!-- VC++ 2003 can't compile current SSQLS code -->
      <exe id="for_each" template="libexcommon-user,programs">
        <sources>examples/for_each.cpp</sources>


      </exe>

    </if>

    <exe id="load_jpeg" template="libexcommon-user,programs">
      <sources>examples/load_jpeg.cpp</sources>
    </exe>
    <exe id="multiquery" template="libexcommon-user,programs">
      <sources>examples/multiquery.cpp</sources>
    </exe>
    <exe id="resetdb" template="libexcommon-user,programs">
      <sources>examples/resetdb.cpp</sources>
    </exe>
    <exe id="simple1" template="libexcommon-user,programs">
      <sources>examples/simple1.cpp</sources>
    </exe>

    <exe id="simple2" template="libexcommon-user,programs">
      <sources>examples/simple2.cpp</sources>
    </exe>

    <exe id="simple3" template="libexcommon-user,programs">
      <sources>examples/simple3.cpp</sources>


    </exe>
    <if cond="FORMAT!='msvs2003prj'">
      <!-- VC++ 2003 can't compile current SSQLS code -->

      <exe id="ssqls1" template="libexcommon-user,programs">
        <sources>examples/ssqls1.cpp</sources>
      </exe>

      <exe id="ssqls2" template="libexcommon-user,programs">
        <sources>examples/ssqls2.cpp</sources>
      </exe>

      <exe id="ssqls3" template="libexcommon-user,programs">

        <sources>examples/ssqls3.cpp</sources>
      </exe>

      <exe id="ssqls4" template="libexcommon-user,programs">

        <sources>examples/ssqls4.cpp</sources>
      </exe>
      <exe id="ssqls5" template="libexcommon-user,programs">

        <sources>examples/ssqls5.cpp</sources>

      </exe>
      <exe id="ssqls6" template="libexcommon-user,programs">$
        <sources>examples/ssqls6.cpp</sources>
      </exe>$
      <exe id="store_if" template="libexcommon-user,programs">

        <sources>examples/store_if.cpp</sources>
      </exe>

    </if>
    <exe id="tquery1" template="libexcommon-user,programs">
      <sources>examples/tquery1.cpp</sources>
    </exe>
    <exe id="tquery2" template="libexcommon-user,programs">
      <sources>examples/tquery2.cpp</sources>
    </exe>
    <exe id="tquery3" template="libexcommon-user,programs">
      <sources>examples/tquery3.cpp</sources>
    </exe>
    <exe id="tquery4" template="libexcommon-user,programs">
      <sources>examples/tquery4.cpp</sources>


    </exe>
    <if cond="FORMAT!='msvs2003prj'">
      <!-- VC++ 2003 can't compile current SSQLS code -->
      <exe id="transaction" template="libexcommon-user,programs">

        <sources>examples/transaction.cpp</sources>
      </exe>
    </if>
  </if>   <!-- build examples -->






  <if cond="FORMAT=='autoconf'">
    <set var="PKGNAME">@PACKAGE_NAME@-@PACKAGE_VERSION@</set>

    <modify-target target="clean">
      <command>
        rm -rf doc/latex doc/pdf ; \
        cd doc/html/refman ; \
        rm -f doxygen.css [a-z]*.{dot,html,map,md5,png}
      </command>
    </modify-target>


    <modify-target target="uninstall">
      <command>
        -rmdir $(HEADER_DIR)
      </command>
      <command>
        rm -f $(DESTDIR)$(libdir)/$(DLLPREFIX)mysqlpp.$(SO_SUFFIX)
      </command>
    </modify-target>






    <action id="Makefile">
      <depends-on-file>configure.ac</depends-on-file>
      <depends-on-file>install.hta.in</depends-on-file>
      <depends-on-file>mysql++.bkl</depends-on-file>
      <depends-on-file>mysql++.spec.in</depends-on-file>
      <depends-on-file>doc/userman/userman.dbx.in</depends-on-file>
      <depends-on-file>lib/Doxyfile.in</depends-on-file>
      <depends-on-file>lib/mysql++.h.in</depends-on-file>

      <depends-on-file>ssx/Doxyfile.in</depends-on-file>
      <command>bakefile_gen</command>
      <command>./config.status</command>
    </action>

    <action id="lib/ssqls.h">

      <command>cd lib ; ./ssqls.pl</command>




      <depends-on-file>lib/ssqls.pl</depends-on-file>
    </action>




    <action id="lib/querydef.h">
      <command>cd lib ; ./querydef.pl</command>
      <depends-on-file>lib/querydef.pl</depends-on-file>
    </action>


    <action id="tags">

      <is-phony/>



      <command>ctags --recurse=yes .</command>
    </action>


    <action id="ctags"><depends>tags</depends></action>

    <action id="doc/html/refman/index.html">
      <depends-on-file>lib/Doxyfile</depends-on-file>
      <depends-on-file>lib/*.cpp</depends-on-file>
      <depends-on-file>lib/*.h</depends-on-file>
      <command>
        cd lib ; doxygen > /dev/null
      </command>
    </action>






    <action id="doc/html/refman/ssx/index.html">

      <depends-on-file>ssx/Doxyfile</depends-on-file>
      <depends-on-file>ssx/*.cpp</depends-on-file>
      <depends-on-file>ssx/*.h</depends-on-file>
      <command>
        cd ssx ; doxygen > /dev/null
      </command>

    </action>

    <action id="doc/html/userman/index.html">
      <depends-on-file>doc/userman/*.dbx</depends-on-file>
      <depends-on-file>doc/userman/userman.dbx.in</depends-on-file>

      <command>
        cd doc/userman ; make html pdf ; cp userman.pdf ../pdf

      </command>



    </action>


    <action id="doc">
      <depends>doc/html/refman/index.html</depends>
      <depends>doc/html/refman/ssx/index.html</depends>
      <depends>doc/html/userman/index.html</depends>
    </action>



    <action id="@PACKAGE_NAME@-@PACKAGE_VERSION@">
      <!-- Set up package directory -->
      <command>
        for d in config doc/html/refman doc/html/userman \
            doc/refman doc/userman examples lib ssx test ; \
        do \



          mkdir -p $(PKGNAME)/$(DDD) ; \
        done
      </command>

      <!-- Copy files into package directory -->
      <!-- top directory -->

      <command>
        cp -RL *.bat *.in *.txt Bakefiles.bkgen bootstrap ChangeLog \
          cleanmf config.guess config.sub configure* dtest exrun \
          install* Makefile.* mysql++.* osver Wishlist $(PKGNAME)
      </command>






      <!-- VC++ project file subdirs -->
      <command>
        for d in vc200? ; do \
          mkdir -p $(PKGNAME)/$(DDD) ; \
          cp $(DDD)/*.sln $(DDD)/*.vcproj $(PKGNAME)/$(DDD) ; \
        done
      </command>







      <!-- config subdir -->






      <command>cp config/*.m4 $(PKGNAME)/config</command>



      <!-- doc subdir -->
      <if cond="BUILDDOCS=='yes'">
        <command>
          cp -RL doc/README* doc/pdf doc/ssqls-pretty $(PKGNAME)/doc

        </command>

        <command>
          for f in fo2pdf LICENSE.txt Makefile Makefile.hello.* mktxt README.txt \*.dbx \*.in \*.mod \*.txt \*.xsl ; \
          do \
            cp doc/userman/$(DDF) $(PKGNAME)/doc/userman ; \
          done
        </command>


        <command>


          for d in refman userman ; do \
            for f in *.css *.html ; do \

              cp doc/html/$(DDD)/$(DDF) $(PKGNAME)/doc/html/$(DDD) ; \

            done ; \
          done
        </command>
        <command>
          cp doc/html/refman/*.png $(PKGNAME)/doc/html/refman
        </command>
      </if>
      <if cond="BUILDDOCS!='yes'">
        <!-- We have to copy this file even though we don't
           build the docs to make configure happy, because it
           wants to update the version number. -->
        <command>
          cp doc/userman/userman.dbx.in $(PKGNAME)/doc/userman
        </command>
      </if>



      <!-- examples subdir -->
      <command>
        cp examples/*.cpp examples/*.h examples/*.jpg $(PKGNAME)/examples
      </command>
      <command>

        for d in mfc wforms ; \
        do \
          mkdir -p $(PKGNAME)/examples/vstudio/$(DDD) ; \
          cp examples/vstudio/$(DDD)/* $(PKGNAME)/examples/vstudio/$(DDD) ; \


        done
      </command>

      <!-- lib subdir -->
      <command>


        cp lib/*.cpp lib/*.h lib/*.in lib/*.pl $(PKGNAME)/lib


      </command>





















      <!-- test subdir -->
      <command>
        cp test/*.cpp $(PKGNAME)/test
      </command>

      <!-- ssx subdir -->
      <command>
        cp ssx/*.cpp ssx/*.h ssx/*.in $(PKGNAME)/ssx
      </command>

      <!-- re-bootstrap it to get a standard configuration -->
      <command>cd $(PKGNAME) ; ./bootstrap nodoc nomaint</command>
      <command>rm -f $(PKGNAME)/Makefile</command>
      <command>rm -f $(PKGNAME)/config.log</command>
      <command>rm -f $(PKGNAME)/config.status</command>
      <command>rm -fr $(PKGNAME)/autom4te.cache</command>
    </action>










    <action id="abicheck">
      <command>
        <![CDATA[
          abi-compliance-checker -lib mysqlpp -dump abi.xml
          abi-compliance-checker -lib mysqlpp \
              -old $(OLDABIDIR)/mysqlpp_$(STABLEABI).abi.tar.gz \
              -new $(NEWABIDIR)/mysqlpp_@PACKAGE_VERSION@.abi.tar.gz
          mv compat_reports/mysqlpp/*/compat_report.html ~/Desktop
          find compat_reports -empty -delete
        ]]>
      </command>
    </action>

    <action id="dist">


      <depends>doc</depends>
      <depends>$(PKGNAME)</depends>
      <command>tar czf $(PKGNAME).tar.gz $(PKGNAME)</command>
      <command>rm -rf $(PKGNAME)</command>


    </action>




    <action id="rpm">
      <if cond="BUILDDOCS=='yes'">
        <depends>doc</depends>
      </if>
      <depends>dist</depends>
      <command>cp $(PKGNAME).tar.gz ~/rpmbuild/SOURCES</command>
      <command>cd ~/rpmbuild/SPECS</command>
      <command>rpmbuild -ba mysql++.spec</command>
    </action>

    <action id="ebuild">
      <depends>dist</depends>
      <command>cp $(PKGNAME).tar.gz /usr/portage/distfiles</command>
      <command>
        cp mysql++.ebuild /usr/portage/dev-db/mysql++/$(PKGNAME).ebuild

      </command>
      <command>
        ebuild /usr/portage/dev-db/mysql++/$(PKGNAME).ebuild digest
      </command>
    </action>
  </if>
</makefile>

Changes to lib/field.h.

1
2

3
4

5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
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
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
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
144
145
146
147
148
149
150
151
152
153
154
155
156
157
/// \file field.h
/// \brief Declares the Field and Fields classes.


/***********************************************************************

 Copyright (c) 2007 by Educational Technology Resources, Inc.
 Others may also hold copyrights on code in this file.  See the
 CREDITS.txt file in the top directory of the distribution for details.

 This file is part of MySQL++.

 MySQL++ is free software; you can redistribute it and/or modify it
 under the terms of the GNU Lesser General Public License as published
 by the Free Software Foundation; either version 2.1 of the License, or
 (at your option) any later version.

 MySQL++ is distributed in the hope that it will be useful, but WITHOUT
 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
 License for more details.

 You should have received a copy of the GNU Lesser General Public
 License along with MySQL++; if not, write to the Free Software
 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
 USA
***********************************************************************/

#if !defined(MYSQLPP_FIELD_H)
#define MYSQLPP_FIELD_H

#include "common.h"
#include "type_info.h"

#include <vector>

namespace mysqlpp {

/// \brief Class to hold information about a SQL field
///
/// This is a cut-down version of MYSQL_FIELD, using MySQL++ and generic
/// C++ types instead of the C types it uses, and hiding all fields
/// behind accessors.  It leaves out data members we have decided aren't
/// very useful.  Given a good argument, we're willing to mirror more of
/// the fields; we just don't want to mirror the underlying structure
/// slavishly for no benefit.

class Field
{
public:
	/// \brief Create empty object
	Field() :
	length_(0),
	max_length_(0),
	flags_(0)
	{
	}

	/// \brief Create object from C API field structure
	Field(const MYSQL_FIELD* pf) :
	name_(pf->name),
	table_(pf->table),
#if MYSQL_VERSION_ID > 40000	// only in 4.0 +
	db_(pf->db),
#endif
	type_(pf->type, (pf->flags & UNSIGNED_FLAG) != 0,
			(pf->flags & NOT_NULL_FLAG) == 0),
	length_(pf->length),
	max_length_(pf->max_length),
	flags_(pf->flags)
	{
	}

	/// \brief Create object as a copy of another Field
	Field(const Field& other) :
	name_(other.name_),
	table_(other.table_),
	db_(other.db_),
	type_(other.type_),
	length_(other.length_),
	max_length_(other.max_length_),
	flags_(other.flags_)
	{
	}

	/// \brief Returns true if field auto-increments
	bool auto_increment() const { return flags_ & AUTO_INCREMENT_FLAG; }

	/// \brief Returns true if field is of some binary type
	bool binary_type() const { return flags_ & BINARY_FLAG; }

	/// \brief Returns true if field is of some BLOB type
	bool blob_type() const { return flags_ & BLOB_FLAG; }

	/// \brief Return the name of the database the field comes from
	const char* db() const { return db_.c_str(); }

	/// \brief Returns true if field is of an enumerated value type
	bool enumeration() const { return flags_ & ENUM_FLAG; }

	/// \brief Return the creation size of the field
	///
	/// This is the number of bytes the field can hold, not how much is
	/// actually stored in the field on any particular row.
	size_t length() const { return length_; }

	/// \brief Return the maximum number of bytes stored in this field
	/// in any of the rows in the result set we were created from.
	size_t max_length() const { return max_length_; }

	/// \brief Returns true if field is part of a key
	bool multiple_key() const { return flags_ & MULTIPLE_KEY_FLAG; }

	/// \brief Return the field's name
	const char* name() const { return name_.c_str(); }

#if defined(NO_DEFAULT_VALUE_FLAG)
	/// \brief Returns true if field has no default value
	bool no_default() const { return flags_ & NO_DEFAULT_VALUE_FLAG; }
#endif

	/// \brief Returns true if field is part of a primary key
	bool primary_key() const { return flags_ & PRI_KEY_FLAG; }

	/// \brief Returns true if field is of some 'set' type
	bool set_type() const { return flags_ & SET_FLAG; }

	/// \brief Return the name of the table the field comes from
	const char* table() const { return table_.c_str(); }

	/// \brief Returns true if field's type is timestamp
	bool timestamp() const { return flags_ & TIMESTAMP_FLAG; }

	/// \brief Return information about the field's type
	const mysql_type_info& type() const { return type_; }

	/// \brief Returns true if field is part of a unique key
	bool unique_key() const { return flags_ & UNIQUE_KEY_FLAG; }

	/// \brief Returns true if field has the zerofill attribute
	bool zerofill() const { return flags_ & ZEROFILL_FLAG; }

private:
	std::string name_;		///< the field's name
	std::string table_;		///< name of table field comes from
	std::string db_;		///< name of database field comes from
	mysql_type_info type_;	///< info about the field's type
	size_t length_;			///< creation size of column
	size_t max_length_;		///< size of largest item in column in result set
	unsigned int flags_;	///< DB engine-specific set of bit flags
};


/// \brief The list-of-Fields type
typedef std::vector<Field> Fields;

} // end namespace mysqlpp

#endif // !defined(MYSQLPP_FIELD_H)
|
|
>

<
>
|
|
|



















|
|

<
<
<
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<

<
<
|
<
<
|
<
<
<
<
<
|
<
<
<
|
<
<
|
<
<
|
<
<
<
<
|
<
<

<
<
|
<
<

<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
1
2
3
4

5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30



31


























































32


33


34





35



36


37


38




39


40


41


42





























/***********************************************************************
 printdata.h - Declares utility routines for printing out data in
	common forms, used by most of the example programs.


 Copyright (c) 1998 by Kevin Atkinson, (c) 1999-2001 by MySQL AB, and
 (c) 2004-2007 by Educational Technology Resources, Inc.  Others may
 also hold copyrights on code in this file.  See the CREDITS file in
 the top directory of the distribution for details.

 This file is part of MySQL++.

 MySQL++ is free software; you can redistribute it and/or modify it
 under the terms of the GNU Lesser General Public License as published
 by the Free Software Foundation; either version 2.1 of the License, or
 (at your option) any later version.

 MySQL++ is distributed in the hope that it will be useful, but WITHOUT
 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
 License for more details.

 You should have received a copy of the GNU Lesser General Public
 License along with MySQL++; if not, write to the Free Software
 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
 USA
***********************************************************************/

#if !defined(MYSQLPP_PRINTDATA_H)
#define MYSQLPP_PRINTDATA_H




#include <mysql++.h>





























































void print_stock_header(int rows);


void print_stock_row(const mysqlpp::Row& r);





void print_stock_row(const mysqlpp::sql_char& item,



		mysqlpp::sql_bigint num, mysqlpp::sql_double weight,


		mysqlpp::sql_decimal price, const mysqlpp::sql_date& date);


void print_stock_rows(mysqlpp::StoreQueryResult& res);




void print_stock_table(mysqlpp::Query& query);





#endif // !defined(MYSQLPP_PRINTDATA_H)
































Changes to lib/field_names.cpp.

1



2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27

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


56
57
58
59
60


61
62




63



64
65
66
67


/***********************************************************************



 field_names.cpp - Implements the FieldNames class.

 Copyright (c) 1998 by Kevin Atkinson, (c) 1999-2001 by MySQL AB, and
 (c) 2004-2010 by Educational Technology Resources, Inc.  Others may
 also hold copyrights on code in this file.  See the CREDITS.txt file
 in the top directory of the distribution for details.

 This file is part of MySQL++.

 MySQL++ is free software; you can redistribute it and/or modify it
 under the terms of the GNU Lesser General Public License as published
 by the Free Software Foundation; either version 2.1 of the License, or
 (at your option) any later version.

 MySQL++ is distributed in the hope that it will be useful, but WITHOUT
 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
 License for more details.

 You should have received a copy of the GNU Lesser General Public
 License along with MySQL++; if not, write to the Free Software
 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
 USA
***********************************************************************/

#define MYSQLPP_NOT_HEADER

#include "common.h"

#include "field_names.h"

#include "result.h"

#include <algorithm>

namespace mysqlpp {

namespace internal { extern void str_to_lwr(std::string& s); }



void
FieldNames::init(const ResultBase* res)
{
	size_t num = res->num_fields();


	reserve(num);





	for (size_t i = 0; i < num; i++) {
		push_back(res->fields().at(i).name());


	}
}














unsigned int
FieldNames::operator [](const std::string& s) const




{

	std::string temp1(s);


	internal::str_to_lwr(temp1);


	for (const_iterator it = begin(); it != end(); ++it) {
	std::string temp2(*it);
		internal::str_to_lwr(temp2);
		if (temp2.compare(temp1) == 0) {
			return it - begin();


		}
	}








	return end() - begin();
}

} // end namespace mysqlpp



>
>
>
|

<
|
|
|



















|
>
|

|
>
|

|

<

<
>
>
|
<
|
|
|
>
>
|
>
|
>
>
>
|
<
>
>
|
|
>
>
>
>
>
>
>
>
|
>
>
>
>
|
|
<
>
>
>
>
|
>
|
>
>
|
>
>
|
<
<
<
|
>
>


>
>
>
>
|
>
>
>
|
|

<
>
>
1
2
3
4
5
6

7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
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
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73

74
75
76
77
78
79
80
81
82
83
84
85
86



87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102

103
104
/***********************************************************************
 store_if.cpp - Demonstrates Query::store_if(), showing only the rows
	from the sample table with prime quantities.  This isn't intended
	to be useful, only to show how you can do result set filtering that
	outstrips the power of SQL.


 Copyright (c) 2005-2010 by Educational Technology Resources, Inc.
 Others may also hold copyrights on code in this file.  See the CREDITS
 file in the top directory of the distribution for details.

 This file is part of MySQL++.

 MySQL++ is free software; you can redistribute it and/or modify it
 under the terms of the GNU Lesser General Public License as published
 by the Free Software Foundation; either version 2.1 of the License, or
 (at your option) any later version.

 MySQL++ is distributed in the hope that it will be useful, but WITHOUT
 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
 License for more details.

 You should have received a copy of the GNU Lesser General Public
 License along with MySQL++; if not, write to the Free Software
 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
 USA
***********************************************************************/

#include "cmdline.h"
#include "printdata.h"
#include "stock.h"

#include <mysql++.h>

#include <iostream>

#include <math.h>




// Define a functor for testing primality.
struct is_prime
{

	bool operator()(const stock& s)
	{
		if ((s.num == 2) || (s.num == 3)) {
			return true;	// 2 and 3 are trivial cases
		}
		else if ((s.num < 2) || ((s.num % 2) == 0)) {
			return false;	// can't be prime if < 2 or even
		}
		else {
			// The only possibility left is that it's divisible by an
			// odd number that's less than or equal to its square root.
			for (int i = 3; i <= sqrt(double(s.num)); i += 2) {

				if ((s.num % i) == 0) {
					return false;
				}
			}
			return true;
		}
	}
};


int
main(int argc, char *argv[])
{
	// Get database access parameters from command line
	mysqlpp::examples::CommandLine cmdline(argc, argv);
	if (!cmdline) {
		return 1;
	}


	try {
		// Establish the connection to the database server.
		mysqlpp::Connection con(mysqlpp::examples::db_name,
				cmdline.server(), cmdline.user(), cmdline.pass());

		// Collect the stock items with prime quantities
		std::vector<stock> results;
		mysqlpp::Query query = con.query();
		query.store_if(results, stock(), is_prime());

		// Show the results
		print_stock_header(results.size());
		std::vector<stock>::const_iterator it;



		for (it = results.begin(); it != results.end(); ++it) {
			print_stock_row(it->item.c_str(), it->num, it->weight,
					it->price, it->sDate);
		}
	}
	catch (const mysqlpp::BadQuery& e) {
		// Something went wrong with the SQL query.
		std::cerr << "Query failed: " << e.what() << std::endl;
		return 1;
	}
	catch (const mysqlpp::Exception& er) {
		// Catch-all for any other MySQL++ exceptions
		std::cerr << "Error: " << er.what() << std::endl;
		return 1;
	}


	return 0;
}

Changes to lib/field_names.h.


1
2


3


4






5




6



7



8




9

10




11





12



13





14














15

















16

17



18

19





20







21







22



23




24










25
26





27




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
56














































57
58


59










60






61
62
63
64
65
66





67
68
















69
70
71






72


73
74


























































75


76
77







78
79






80
81













82




83
84




85
86




87








88
89




90



91







92
93




94









95








96


97




98
99


100






























101
102









103

104




105
106




107




108
109
110







111






112
113
114
115


116






117










118


/// \file field_names.h
/// \brief Declares a class to hold a list of field names.





/***********************************************************************






 Copyright (c) 1998 by Kevin Atkinson, (c) 1999-2001 by MySQL AB, and




 (c) 2004-2008 by Educational Technology Resources, Inc.  Others may



 also hold copyrights on code in this file.  See the CREDITS.txt file



 in the top directory of the distribution for details.






 This file is part of MySQL++.










 MySQL++ is free software; you can redistribute it and/or modify it



 under the terms of the GNU Lesser General Public License as published





 by the Free Software Foundation; either version 2.1 of the License, or














 (at your option) any later version.



















 MySQL++ is distributed in the hope that it will be useful, but WITHOUT



 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or

 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public





 License for more details.















 You should have received a copy of the GNU Lesser General Public



 License along with MySQL++; if not, write to the Free Software




 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301










 USA
***********************************************************************/










#ifndef MYSQLPP_FIELD_NAMES_H
#define MYSQLPP_FIELD_NAMES_H





#include <string>

#include <vector>










namespace mysqlpp {







#if !defined(DOXYGEN_IGNORE)






// Make Doxygen ignore this

class MYSQLPP_EXPORT ResultBase;
#endif















/// \brief Holds a list of SQL field names






class FieldNames : public std::vector<std::string>






{





public:
	/// \brief Default constructor
	FieldNames() { }


	/// \brief Copy constructor
	FieldNames(const FieldNames& other) :
	std::vector<std::string>()
	{

		assign(other.begin(), other.end());
	}
	
	/// \brief Create field name list from a result set
	FieldNames(const ResultBase* res) :














































	std::vector<std::string>()
	{


		init(res);










	}







	/// \brief Create empty field name list, reserving space for
	/// a fixed number of field names.
	FieldNames(int i) :
	std::vector<std::string>(i)
	{





	}

















	/// \brief Initializes the field list from a result set
	FieldNames& operator =(const ResultBase* res)
	{






		init(res);


		return *this;
	}





























































	/// \brief Insert \c i empty field names at beginning of list
	FieldNames& operator =(int i)







	{
		insert(begin(), i, "");






		return *this;
	}


















	/// \brief Get the name of a field given its index.
	std::string& operator [](int i)




	{
		return at(i);




	}









	/// \brief Get the name of a field given its index, in const




	/// context.



	const std::string& operator [](int i) const







	{
		return at(i);




	}


















	/// \brief Get the name of a field given its index.


	std::string& operator [](size_type i)




	{
		return at(i);


	}































	/// \brief Get the name of a field given its index, in const









	/// context.

	const std::string& operator [](size_type i) const




	{
		return at(i);




	}





	/// \brief Get the index number of a field given its name
	unsigned int operator [](const std::string& s) const;














private:
	void init(const ResultBase* res);
};



} // end namespace mysqlpp

















#endif

>
|
|
>
>

>
>
|
>
>
>
>
>
>
|
>
>
>
>
|
>
>
>
|
>
>
>
|
>
>
>
>

>
|
>
>
>
>

>
>
>
>
>
|
>
>
>
|
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

>
|
>
>
>
|
>
|
>
>
>
>
>
|
>
>
>
>
>
>
>

>
>
>
>
>
>
>
|
>
>
>
|
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
|
<
>
>
>
>
>

>
>
>
>
|
<

>
>
>
>
|
>
|
>
>
>
>
>

>
>
>
>
|
>
>

>
>
>
>
|
>
>
>
>
>
>
|
>
|
|
>
>
>
>
>
>
>

>
>
>
>
>
>
>
|
>
>
>
>
>
>
|
>
>
>
>
>
>
|
>
>
>
>
>
|
|
<
>
|
|
|
|
<
>
|
|
|
<
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
<
>
>
|
>
>
>
>
>
>
>
>
>
>
|
>
>
>
>
>
>
|
<
<
<
<
|
>
>
>
>
>
|
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
<
<
>
>
>
>
>
>
|
>
>
|
<
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

>
>
|
<
>
>
>
>
>
>
>
|
|
>
>
>
>
>
>
|
|
>
>
>
>
>
>
>
>
>
>
>
>
>

>
>
>
>
|
<
>
>
>
>
|
|
>
>
>
>
|
>
>
>
>
>
>
>
>

<
>
>
>
>
|
>
>
>
|
>
>
>
>
>
>
>
|
|
>
>
>
>
|
>
>
>
>
>
>
>
>
>

>
>
>
>
>
>
>
>
|
>
>
|
>
>
>
>
|
<
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

<
>
>
>
>
>
>
>
>
>
|
>
|
>
>
>
>
|
<
>
>
>
>
|
>
>
>
>

<
<
>
>
>
>
>
>
>

>
>
>
>
>
>
|
<
<

>
>
|
>
>
>
>
>
>

>
>
>
>
>
>
>
>
>
>
|
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
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
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
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
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
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225

226
227
228
229
230

231
232
233
234

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
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
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
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
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400

401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436

437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456

457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506

507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540

541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557

558
559
560
561
562
563
564
565
566
567


568
569
570
571
572
573
574
575
576
577
578
579
580
581
582


583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
<?xml version="1.0"?>
<makefile>
  <requires version="0.2.5"/>
  <using module="datafiles"/>
  <include file="presets/simple.bkl"/>

  <set var="DDD">$(DOLLAR)$(DOLLAR)d</set>
  <set var="DDF">$(DOLLAR)$(DOLLAR)f</set>

  <set var="PLATFORM_WINDOWS_NATIVE">no</set>
  <set var="THREAD_TYPE">single</set>
  <if cond="FORMAT in ['msvs2003prj', 'msvs2005prj', 'msvs2008prj', 'mingw']">
    <set var="PLATFORM_WINDOWS_NATIVE">yes</set>
    <set var="THREAD_TYPE">multi</set>
  </if>
    
  <option name="BUILD">
    <values>debug,release</values>
    <values-description>Debug,Release</values-description>
    <default-value>debug</default-value>
    <description>
      Type of compiled binaries
    </description>
  </option>

  <set var="MYSQL_WIN_DIR">
    C:\Program Files\MySQL\MySQL Server 5.1
  </set>

  <set var="DEBUGINFO">
    <if cond="BUILD=='debug'">on</if>
    <if cond="BUILD=='release'">off</if>
  </set>

  <!-- This convoluted syntax adds "_d" to the end of library and DLL
     file names for VC++ and Xcode, in debug mode only. -->
  <set var="DEBUG_SUFFIX"/>
  <set var="DEBUG_SUFFIX">
    <if cond="FORMAT in ['msvs2003prj', 'msvs2005prj', 'msvs2008prj', 'xcode2'] and BUILD=='debug'">_d</if>
  </set>

  <set var="BUILDDOCS">yes</set>
  <set var="BUILDEXAMPLES">yes</set>
  <set var="BUILDLIBRARY">yes</set>
  <set var="BUILDTEST">yes</set>
  <set var="HEADER_DIR">$(PREFIX)/include/mysql++</set>

  <if cond="FORMAT in ['msvs2003prj', 'msvs2005prj', 'msvs2008prj']">
    <set-srcdir>..</set-srcdir>
  </if>

  <if cond="BUILDLIBRARY=='yes'">
    <dll id="mysqlpp">
      <dllname>mysqlpp$(DEBUG_SUFFIX)</dllname>
      <libname>mysqlpp$(DEBUG_SUFFIX)</libname>
      <so_version>3.1.0</so_version>

      <sources>
        lib/beemutex.cpp
        lib/cmdline.cpp
        lib/connection.cpp
        lib/cpool.cpp
        lib/datetime.cpp
        lib/dbdriver.cpp
        lib/field_names.cpp
        lib/field_types.cpp
        lib/manip.cpp
        lib/myset.cpp
        lib/mysql++.cpp
        lib/mystring.cpp
        lib/null.cpp
        lib/options.cpp
        lib/qparms.cpp
        lib/query.cpp
        lib/result.cpp
        lib/row.cpp
        lib/scopedconnection.cpp
        lib/sql_buffer.cpp
        lib/sqlstream.cpp
        lib/ssqls2.cpp
        lib/stadapter.cpp
        lib/tcp_connection.cpp
        lib/transaction.cpp
        lib/type_info.cpp
        lib/uds_connection.cpp
        lib/utility.cpp
        lib/vallist.cpp
        lib/wnp_connection.cpp
      </sources>

      <debug-info>$(DEBUGINFO)</debug-info>

      <threading>$(THREAD_TYPE)</threading>
      <cxx-rtti>on</cxx-rtti>
      <cxx-exceptions>on</cxx-exceptions>
      
      <install-to>$(LIBDIR)</install-to>
      
      <if cond="PLATFORM_WINDOWS_NATIVE=='yes'">
        <define>UNICODE</define>
        <define>_UNICODE</define>
        <sys-lib>wsock32</sys-lib>
      </if>

      <if cond="FORMAT in ['msvs2003prj', 'msvs2005prj', 'msvs2008prj']">
        <define>MYSQLPP_MAKING_DLL</define>
        <define>HAVE_MYSQL_SSL_SET</define>
        <include>$(MYSQL_WIN_DIR)\include</include>
        <lib-path>$(MYSQL_WIN_DIR)\lib\opt</lib-path>
        <sys-lib>libmysql</sys-lib>
      </if>

      <if cond="FORMAT=='mingw'">
        <define>MYSQLPP_NO_DLL</define>
        <define>HAVE_MYSQL_SSL_SET</define>
        <include>"$(MYSQL_WIN_DIR)\include"</include>
        <lib-path>"$(MYSQL_WIN_DIR)\lib\opt"</lib-path>
        <sys-lib>mysqlclient</sys-lib>
      </if>

      <if cond="FORMAT=='autoconf'">
        <depends>lib/ssqls.h</depends>
        <depends>lib/querydef.h</depends>

        <cxxflags>@PTHREAD_CFLAGS@</cxxflags>
        <include>.</include>
        <ldflags>-l@MYSQL_C_LIB_NAME@ @PTHREAD_LIBS@ @MYSQLPP_EXTRA_LIBS@</ldflags>
      </if>

      <if cond="FORMAT=='xcode2'">
        <define>HAVE_POSIX_GETOPT</define>
        <define>MYSQLPP_XCODE</define>
	    <include>/usr/local/mysql/include</include>
        <ldflags>-lmysqlclient</ldflags>
		<!-- Assume C API files came from MySQL.com DMGs, not source
		     tarball, Fink, etc., inferring preference from use of Xcode. -->
        <lib-path>/usr/local/mysql/lib</lib-path>
      </if>
    </dll>


    <data-files>
      <files>lib/*.h</files>
      <install-to>$(HEADER_DIR)</install-to>
    </data-files>
  </if>   <!-- build library -->

  <!-- Set up build options common to all built executables -->
  <template id="programs">
    <if cond="BUILDLIBRARY=='yes'">
      <depends>mysqlpp</depends>
    </if>


    <threading>$(THREAD_TYPE)</threading>
    <cxx-rtti>on</cxx-rtti>
    <cxx-exceptions>on</cxx-exceptions>
    <debug-info>$(DEBUGINFO)</debug-info>

    <if cond="FORMAT in ['autoconf', 'gnu', 'mingw', 'xcode2']">
      <include>lib</include>
      <lib-path>.</lib-path>
    </if>
    <if cond="FORMAT in ['msvs2003prj', 'msvs2005prj', 'msvs2008prj']">
      <include>../lib</include>
    </if>

    <if cond="FORMAT=='xcode2'">
      <define>HAVE_POSIX_GETOPT</define>
      <define>MYSQLPP_XCODE</define>
	  <include>/usr/local/mysql/include</include>
      <ldflags>-lmysqlclient</ldflags>
      <lib-path>/usr/local/mysql/lib</lib-path>
    </if>

    <if cond="PLATFORM_WINDOWS_NATIVE=='yes'">
      <define>UNICODE</define>
      <define>_UNICODE</define>
    </if>

    <if cond="FORMAT=='autoconf'">
      <cxxflags>@PTHREAD_CFLAGS@</cxxflags>
      <ldflags>-l@MYSQL_C_LIB_NAME@ @PTHREAD_LIBS@ @MYSQLPP_EXTRA_LIBS@</ldflags>
      <warnings>max</warnings>
      <sys-lib>mysqlpp</sys-lib>
    </if>

    <if cond="FORMAT=='mingw'">
      <define>MYSQLPP_NO_DLL</define>
      <ldflags>
        -Wl,--enable-auto-import -Wl,--enable-runtime-pseudo-reloc
      </ldflags>
      <include>"$(MYSQL_WIN_DIR)\include"</include>
      <lib-path>"$(MYSQL_WIN_DIR)\lib\opt"</lib-path>
      <sys-lib>mysqlclient</sys-lib>
      <sys-lib>mysqlpp$(DEBUG_SUFFIX)</sys-lib>
    </if>

    <if cond="FORMAT in ['msvs2003prj', 'msvs2005prj', 'msvs2008prj']">
      <lib-path>$(BUILD)</lib-path>
      <include>$(MYSQL_WIN_DIR)\include</include>
      <lib-path>$(MYSQL_WIN_DIR)\lib\opt</lib-path>
      <sys-lib>mysqlpp$(DEBUG_SUFFIX)</sys-lib>
      <sys-lib>libmysql</sys-lib>
    </if>

    <if cond="FORMAT=='gnu'">
      <include>/usr/include/mysql</include>
      <include>/usr/include/mysql++</include>
      <sys-lib>mysqlpp</sys-lib>
      <sys-lib>mysqlclient</sys-lib>
    </if>

    <if cond="FORMAT=='xcode2'">
      <include>/usr/local/mysql/include</include>
      <sys-lib>mysqlclient</sys-lib>
      <sys-lib>mysqlpp$(DEBUG_SUFFIX)</sys-lib>
    </if>
  </template>

  <!-- SSQLS v2 parser convenience library -->
  <lib id="ssqls2parse" template="programs">
    <libname>mysqlpp_ssqls2parse</libname>
    <sources>ssx/parsev2.cpp</sources>
    <include>.</include>
  </lib>


  <!-- Build rules for ssqlsxlat tool -->
  <exe id="ssqlsxlat" template="programs">
    <sources>ssx/genv2.cpp</sources>
    <sources>ssx/main.cpp</sources>
    <depends>ssqls2parse</depends>

    <sys-lib>mysqlpp_ssqls2parse</sys-lib>
  </exe>

  <!-- Define library testing programs' output targets, if enabled -->

  <if cond="BUILDTEST=='yes'">
    <exe id="test_array_index" template="programs">
      <sources>test/array_index.cpp</sources>
    </exe>
    <exe id="test_cpool" template="programs">
      <sources>test/cpool.cpp</sources>
    </exe>
    <exe id="test_datetime" template="programs">
      <sources>test/datetime.cpp</sources>
    </exe>
    <exe id="test_inttypes" template="programs">
      <sources>test/inttypes.cpp</sources>
    </exe>
    <exe id="test_insertpolicy" template="programs">
      <sources>test/insertpolicy.cpp</sources>
    </exe>
    <exe id="test_manip" template="programs">
      <sources>test/manip.cpp</sources>
    </exe>
    <if cond="FORMAT!='msvs2003prj'">
      <!-- VC++ 2003 can't compile this -->
      <exe id="test_null_comparison" template="programs">
        <sources>test/null_comparison.cpp</sources>
      </exe>
    </if>
    <exe id="test_query_copy" template="programs">
      <sources>test/query_copy.cpp</sources>
    </exe>
    <if cond="FORMAT!='msvs2003prj'">
      <!-- VC++ 2003 can't compile this -->
      <exe id="test_qssqls" template="programs">
        <sources>test/qssqls.cpp</sources>
      </exe>
    </if>
    <exe id="test_qstream" template="programs">
      <sources>test/qstream.cpp</sources>
    </exe>
    <exe id="test_sqlstream" template="programs">
      <sources>test/sqlstream.cpp</sources>
    </exe>
    <exe id="test_ssqls2" template="programs">
      <sources>test/ssqls2.cpp</sources>
      <depends>ssqls2parse</depends>
      <sys-lib>mysqlpp_ssqls2parse</sys-lib>
    </exe>
    <if cond="FORMAT!='msvs2003prj'">
      <!-- VC++ 2003 can't compile this -->
      <exe id="test_string" template="programs">

        <sources>test/string.cpp</sources>
      </exe>
    </if>
    <exe id="test_tcp" template="programs">
      <sources>test/tcp.cpp</sources>
    </exe>
    <exe id="test_uds" template="programs">
      <sources>test/uds.cpp</sources>
    </exe>
    <exe id="test_wnp" template="programs">
      <sources>test/wnp.cpp</sources>
    </exe>
  </if>   <!-- build library test programs -->

  <!-- Define example programs' output targets, if enabled -->
  <if cond="BUILDEXAMPLES=='yes'">
    <!-- Options specific to examples that depend on libexcommon -->
    <template id="libexcommon-user">
      <depends>excommon</depends>
      <sys-lib>mysqlpp_excommon</sys-lib>
    </template>





    <!-- Convenience library of routines used by most examples -->
    <lib id="excommon" template="programs">
      <libname>mysqlpp_excommon</libname>
      <sources>examples/printdata.cpp</sources>
    </lib>

    <!-- The examples themselves -->
    <if cond="FORMAT!='msvs2003prj'">
      <!-- VC++ 2003 can't compile current SSQLS code -->
      <exe id="cgi_jpeg" template="libexcommon-user,programs">
        <sources>examples/cgi_jpeg.cpp</sources>
      </exe>
    </if>
    <exe id="cpool" template="libexcommon-user,programs">
      <sources>examples/cpool.cpp</sources>
    </exe>
    <exe id="dbinfo" template="libexcommon-user,programs">
      <sources>examples/dbinfo.cpp</sources>
    </exe>
    <exe id="deadlock" template="libexcommon-user,programs">
      <sources>examples/deadlock.cpp</sources>
    </exe>
    <exe id="fieldinf" template="libexcommon-user,programs">
      <sources>examples/fieldinf.cpp</sources>


    </exe>
    <if cond="FORMAT!='msvs2003prj'">
      <!-- VC++ 2003 can't compile current SSQLS code -->
      <exe id="for_each" template="libexcommon-user,programs">
        <sources>examples/for_each.cpp</sources>
      </exe>
    </if>
    <exe id="load_jpeg" template="libexcommon-user,programs">
      <sources>examples/load_jpeg.cpp</sources>
    </exe>

    <exe id="multiquery" template="libexcommon-user,programs">
      <sources>examples/multiquery.cpp</sources>
    </exe>
    <exe id="resetdb" template="libexcommon-user,programs">
      <sources>examples/resetdb.cpp</sources>
    </exe>
    <exe id="simple1" template="libexcommon-user,programs">
      <sources>examples/simple1.cpp</sources>
    </exe>
    <exe id="simple2" template="libexcommon-user,programs">
      <sources>examples/simple2.cpp</sources>
    </exe>
    <exe id="simple3" template="libexcommon-user,programs">
      <sources>examples/simple3.cpp</sources>
    </exe>
    <if cond="FORMAT!='msvs2003prj'">
      <!-- VC++ 2003 can't compile current SSQLS code -->
      <exe id="ssqls1" template="libexcommon-user,programs">
        <sources>examples/ssqls1.cpp</sources>
      </exe>
      <exe id="ssqls2" template="libexcommon-user,programs">
        <sources>examples/ssqls2.cpp</sources>
      </exe>
      <exe id="ssqls3" template="libexcommon-user,programs">
        <sources>examples/ssqls3.cpp</sources>
      </exe>
      <exe id="ssqls4" template="libexcommon-user,programs">
        <sources>examples/ssqls4.cpp</sources>
      </exe>
      <exe id="ssqls5" template="libexcommon-user,programs">
        <sources>examples/ssqls5.cpp</sources>
      </exe>
      <exe id="ssqls6" template="libexcommon-user,programs">$
        <sources>examples/ssqls6.cpp</sources>
      </exe>$
      <exe id="store_if" template="libexcommon-user,programs">
        <sources>examples/store_if.cpp</sources>
      </exe>
    </if>
    <exe id="tquery1" template="libexcommon-user,programs">
      <sources>examples/tquery1.cpp</sources>
    </exe>
    <exe id="tquery2" template="libexcommon-user,programs">
      <sources>examples/tquery2.cpp</sources>
    </exe>
    <exe id="tquery3" template="libexcommon-user,programs">
      <sources>examples/tquery3.cpp</sources>
    </exe>
    <exe id="tquery4" template="libexcommon-user,programs">
      <sources>examples/tquery4.cpp</sources>
    </exe>
    <if cond="FORMAT!='msvs2003prj'">
      <!-- VC++ 2003 can't compile current SSQLS code -->
      <exe id="transaction" template="libexcommon-user,programs">
        <sources>examples/transaction.cpp</sources>
      </exe>
    </if>
  </if>   <!-- build examples -->

  <if cond="FORMAT=='autoconf'">
    <set var="PKGNAME">@PACKAGE_NAME@-@PACKAGE_VERSION@</set>


    <modify-target target="clean">
      <command>
        rm -rf doc/latex doc/pdf ; \
        cd doc/html/refman ; \
        rm -f doxygen.css [a-z]*.{dot,html,map,md5,png}
      </command>
    </modify-target>

    <modify-target target="uninstall">
      <command>
        -rmdir $(HEADER_DIR)
      </command>
      <command>
        rm -f $(DESTDIR)$(libdir)/$(DLLPREFIX)mysqlpp.$(SO_SUFFIX)
      </command>
    </modify-target>

    <action id="Makefile">
      <depends-on-file>configure.ac</depends-on-file>
      <depends-on-file>install.hta.in</depends-on-file>
      <depends-on-file>mysql++.bkl</depends-on-file>
      <depends-on-file>mysql++.spec.in</depends-on-file>
      <depends-on-file>doc/userman/userman.dbx.in</depends-on-file>
      <depends-on-file>lib/Doxyfile.in</depends-on-file>
      <depends-on-file>lib/mysql++.h.in</depends-on-file>
      <depends-on-file>ssx/Doxyfile.in</depends-on-file>
      <command>bakefile_gen</command>
      <command>autoreconf</command>
      <command>./config.status</command>
    </action>

    <action id="lib/ssqls.h">
      <command>cd lib ; ./ssqls.pl</command>
      <depends-on-file>lib/ssqls.pl</depends-on-file>
    </action>


    <action id="lib/querydef.h">
      <command>cd lib ; ./querydef.pl</command>
      <depends-on-file>lib/querydef.pl</depends-on-file>
    </action>

    <action id="tags">
      <is-phony/>
      <command>ctags --recurse=yes .</command>
    </action>
    <action id="ctags"><depends>tags</depends></action>

    <action id="doc/html/refman/index.html">
      <depends-on-file>lib/Doxyfile</depends-on-file>
      <depends-on-file>lib/*.cpp</depends-on-file>
      <depends-on-file>lib/*.h</depends-on-file>
      <command>
        cd lib ; doxygen > /dev/null
      </command>
    </action>


    <action id="doc/html/refman/ssx/index.html">
      <depends-on-file>ssx/Doxyfile</depends-on-file>
      <depends-on-file>ssx/*.cpp</depends-on-file>
      <depends-on-file>ssx/*.h</depends-on-file>
      <command>
        cd ssx ; doxygen > /dev/null
      </command>
    </action>

    <action id="doc/html/userman/index.html">
      <depends-on-file>doc/userman/*.dbx</depends-on-file>
      <depends-on-file>doc/userman/userman.dbx.in</depends-on-file>
      <command>
        cd doc/userman ; make html pdf ; cp userman.pdf ../pdf
      </command>
    </action>

    <action id="doc">
      <depends>doc/html/refman/index.html</depends>
      <depends>doc/html/refman/ssx/index.html</depends>
      <depends>doc/html/userman/index.html</depends>
    </action>

    <action id="@PACKAGE_NAME@-@PACKAGE_VERSION@">
      <!-- Set up package directory -->
      <command>
        for d in config doc/html/refman doc/html/userman \
            doc/refman doc/userman examples lib ssx test ; \
        do \
          mkdir -p $(PKGNAME)/$(DDD) ; \
        done
      </command>

      <!-- Copy files into package directory -->
      <!-- top directory -->
      <command>
        cp -RL *.bat *.txt Bakefiles.bkgen bootstrap ChangeLog \
          cleanmf config.guess config.h.in config.sub configure* \
          dtest exrun install* libmysqlclient.def Makefile.* \
          mysql++.* osver Wishlist $(PKGNAME)
      </command>

      <!-- VC++ project file subdirs -->
      <command>
        for d in vc200? ; do \
          mkdir -p $(PKGNAME)/$(DDD) ; \
          cp $(DDD)/*.sln $(DDD)/*.vcproj $(PKGNAME)/$(DDD) ; \
        done
      </command>


      <!-- config subdir -->
      <command>cp config/*.m4 $(PKGNAME)/config</command>

      <!-- doc subdir -->
      <if cond="BUILDDOCS=='yes'">
        <command>
          cp -RL doc/README* doc/pdf doc/ssqls-pretty $(PKGNAME)/doc
        </command>
        <command>
          for f in LICENSE.txt Makefile mktxt README.txt \*.dbx \*.in \*.xsl ; \
          do \
            cp doc/userman/$(DDF) $(PKGNAME)/doc/userman ; \
          done
        </command>
        <command>
          for d in refman userman ; do \
            for f in *.css *.html ; do \
              cp doc/html/$(DDD)/$(DDF) $(PKGNAME)/doc/html/$(DDD) ; \
            done ; \
          done
        </command>
        <command>
          cp doc/html/refman/*.png $(PKGNAME)/doc/html/refman
        </command>
      </if>
      <if cond="BUILDDOCS!='yes'">
        <!-- We have to copy this file even though we don't
           build the docs to make configure happy, because it
           wants to update the version number. -->
        <command>
          cp doc/userman/userman.dbx.in $(PKGNAME)/doc/userman
        </command>
      </if>


      <!-- examples subdir -->
      <command>
        cp examples/*.cpp examples/*.h examples/*.jpg $(PKGNAME)/examples
      </command>
      <command>
        for d in mfc wforms ; \
        do \
          mkdir -p $(PKGNAME)/examples/vstudio/$(DDD) ; \
          cp examples/vstudio/$(DDD)/* $(PKGNAME)/examples/vstudio/$(DDD) ; \
        done
      </command>

      <!-- lib subdir -->
      <command>
        cp lib/*.cpp lib/*.h lib/*.in lib/*.pl $(PKGNAME)/lib
      </command>


      <!-- test subdir -->
      <command>
        cp test/*.cpp $(PKGNAME)/test
      </command>

      <!-- ssx subdir -->
      <command>
        cp ssx/*.cpp ssx/*.h ssx/*.in $(PKGNAME)/ssx
      </command>



      <!-- re-bootstrap it to get a standard configuration -->
      <command>cd $(PKGNAME) ; ./bootstrap nodoc nomaint</command>
      <command>rm -f $(PKGNAME)/Makefile</command>
      <command>rm -f $(PKGNAME)/config.log</command>
      <command>rm -f $(PKGNAME)/config.status</command>
      <command>rm -fr $(PKGNAME)/autom4te.cache</command>
    </action>

    <action id="dist">
      <depends>doc</depends>
      <depends>$(PKGNAME)</depends>
      <command>./checkvc8</command>
      <command>tar czf $(PKGNAME).tar.gz $(PKGNAME)</command>
      <command>rm -rf $(PKGNAME)</command>
    </action>



    <action id="rpm">
      <if cond="BUILDDOCS=='yes'">
        <depends>doc</depends>
      </if>
      <depends>dist</depends>
      <command>cp $(PKGNAME).tar.gz /usr/src/redhat/SOURCES</command>
      <command>cd /usr/src/redhat/SPECS</command>
      <command>rpmbuild -ba mysql++.spec</command>
    </action>

    <action id="ebuild">
      <depends>dist</depends>
      <command>cp $(PKGNAME).tar.gz /usr/portage/distfiles</command>
      <command>
        cp mysql++.ebuild /usr/portage/dev-db/mysql++/$(PKGNAME).ebuild
      </command>
      <command>
        ebuild /usr/portage/dev-db/mysql++/$(PKGNAME).ebuild digest
      </command>
    </action>
  </if>
</makefile>

Changes to lib/field_types.cpp.











1







2


3





4


5





6


7

8



9































10



11

12





13









14



15

16





17





18




19






20


21

22




23









24







25




26

27






28




29

30






31


32







33


34




35



36

37



























38

39
40
41

42


43


44
45


















/***********************************************************************







 field_types.cpp - Implements the FieldTypes class.








 Copyright (c) 1998 by Kevin Atkinson, (c) 1999-2001 by MySQL AB, and


 (c) 2004-2007 by Educational Technology Resources, Inc.  Others may





 also hold copyrights on code in this file.  See the CREDITS.txt file


 in the top directory of the distribution for details.





 This file is part of MySQL++.



































 MySQL++ is free software; you can redistribute it and/or modify it

 under the terms of the GNU Lesser General Public License as published





 by the Free Software Foundation; either version 2.1 of the License, or









 (at your option) any later version.





 MySQL++ is distributed in the hope that it will be useful, but WITHOUT





 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or





 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public




 License for more details.









 You should have received a copy of the GNU Lesser General Public

 License along with MySQL++; if not, write to the Free Software




 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301









 USA







***********************************************************************/






#define MYSQLPP_NOT_HEADER






#include "common.h"






#include "field_types.h"









#include "result.h"










namespace mysqlpp {








void FieldTypes::init(const ResultBase* res)

{



























	size_t num = res->num_fields();

	reserve(num);
	for (size_t i = 0; i < num; i++) {
		push_back(res->field(unsigned(i)).type());

	}


}



} // end namespace mysqlpp








>
>
>
>
>
>
>
>
>
>
|
>
>
>
>
>
>
>
|
>
>

>
>
>
>
>
|
>
>
|
>
>
>
>
>
|
>
>
|
>

>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

>
>
>
|
>
|
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
|
>
>
>

>
|
>
>
>
>
>
|
>
>
>
>
>
|
>
>
>
>
|
>
>
>
>
>
>

>
>
|
>
|
>
>
>
>
|
>
>
>
>
>
>
>
>
>
|
>
>
>
>
>
>
>
|
>
>
>
>

>
|
>
>
>
>
>
>
|
>
>
>
>

>
|
>
>
>
>
>
>

>
>
|
>
>
>
>
>
>
>

>
>
|
>
>
>
>

>
>
>
|
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
|
<
<
>
|
>
>
|
>
>

<
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
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
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
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
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
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241


242
243
244
245
246
247
248
249

250
251
252
253
254
255
256
257
All unit tests passed
---------------- BEGIN resetdb OUTPUT ----------------
Connecting to database server...
Dropping existing sample data tables...
Creating stock table...
Populating stock table...inserted 4 rows.
Creating empty images table...
Creating deadlock testing tables...
Reinitialized sample database successfully.
================ END resetdb OUTPUT ================

---------------- BEGIN simple1 OUTPUT ----------------
We have:
	Nürnberger Brats
	Pickle Relish
	Hot Mustard
	Hotdog Buns
================ END simple1 OUTPUT ================

---------------- BEGIN simple2 OUTPUT ----------------
Item                           Num       Weight    Price     Date

Nürnberger Brats              97        1.5       8.79      2005-03-10
Pickle Relish                  87        1.5       1.75      1998-09-04
Hot Mustard                    73        0.95      0.97      1998-05-25
Hotdog Buns                    65        1.1       1.10      1998-04-23
================ END simple2 OUTPUT ================

---------------- BEGIN simple3 OUTPUT ----------------
Item                           Num       Weight    Price     Date

Nürnberger Brats              97        1.5       8.79      2005-03-10
Pickle Relish                  87        1.5       1.75      1998-09-04
Hot Mustard                    73        0.95      0.97      1998-05-25
Hotdog Buns                    65        1.1       1.10      1998-04-23
================ END simple3 OUTPUT ================

---------------- BEGIN store_if OUTPUT ----------------
Records found: 2

Item                           Num       Weight    Price     Date

Nürnberger Brats              97        1.5       8.79      2005-03-10
Hot Mustard                    73        0.95      0.97      1998-05-25
================ END store_if OUTPUT ================

---------------- BEGIN for_each OUTPUT ----------------
There are 322 items weighing 416.85 stone and costing 1147.19 cowrie shells.
================ END for_each OUTPUT ================

---------------- BEGIN multiquery OUTPUT ----------------
Multi-query: 
DROP TABLE IF EXISTS test_table; CREATE TABLE test_table(id INT); INSERT INTO test_table VALUES(10); UPDATE test_table SET id=20 WHERE id=10; SELECT * FROM test_table; DROP TABLE test_table
Result set 0 is empty.
Result set 1 is empty.
Result set 2 is empty.
Result set 3 is empty.
Result set 4 has 1 row:
  +----+
  | id |
  +----+
  | 20 |
  +----+
Result set 5 is empty.
Stored procedure query: 
DROP PROCEDURE IF EXISTS get_stock; CREATE PROCEDURE get_stock( i_item varchar(20) ) BEGIN SET i_item = concat('%', i_item, '%'); SELECT * FROM stock WHERE lower(item) like lower(i_item); END;
Result set 0 is empty.
Result set 1 is empty.
Query: CALL get_stock('relish')
Result set 0 has 1 row:
  +---------------+-----+--------+-------+------------+-------------+
  |          item | num | weight | price |      sdate | description |
  +---------------+-----+--------+-------+------------+-------------+
  | Pickle Relish |  87 |    1.5 |  1.75 | 1998-09-04 |        NULL |
  +---------------+-----+--------+-------+------------+-------------+
Result set 1 is empty.
================ END multiquery OUTPUT ================

---------------- BEGIN tquery1 OUTPUT ----------------
Query: select * from stock
Records found: 4

Item                           Num       Weight    Price     Date

Nuerenberger Bratwurst         97        1.5       8.79      2005-03-10
Pickle Relish                  87        1.5       1.75      1998-09-04
Hot Mustard                    73        0.95      0.97      1998-05-25
Hotdog Buns                    65        1.1       1.1       1998-04-23
================ END tquery1 OUTPUT ================

---------------- BEGIN resetdb OUTPUT ----------------
Connecting to database server...
Dropping existing sample data tables...
Creating stock table...
Populating stock table...inserted 4 rows.
Creating empty images table...
Creating deadlock testing tables...
Reinitialized sample database successfully.
================ END resetdb OUTPUT ================

---------------- BEGIN tquery2 OUTPUT ----------------
Query: select * from stock
Records found: 4

Item                           Num       Weight    Price     Date

Nuerenberger Bratwurst         97        1.5       8.79      2005-03-10
Pickle Relish                  87        1.5       1.75      1998-09-04
Hot Mustard                    73        0.95      0.97      1998-05-25
Hotdog Buns                    65        1.1       1.1       1998-04-23
================ END tquery2 OUTPUT ================

---------------- BEGIN tquery3 OUTPUT ----------------
Stuff we have a lot of in stock:
	Nuerenberger Bratwurst
	Pickle Relish
================ END tquery3 OUTPUT ================

---------------- BEGIN tquery4 OUTPUT ----------------
Query: update stock set num = 70 where num < 70
Query: select * from stock
Records found: 4

Item                           Num       Weight    Price     Date

Nuerenberger Bratwurst         97        1.5       8.79      2005-03-10
Pickle Relish                  87        1.5       1.75      1998-09-04
Hot Mustard                    73        0.95      0.97      1998-05-25
Hotdog Buns                    70        1.1       1.1       1998-04-23

Query: select * from stock where weight > 1.2 or description like '%Mustard%'
Records found: 3

Item                           Num       Weight    Price     Date

Nuerenberger Bratwurst         97        1.5       8.79      2005-03-10
Pickle Relish                  87        1.5       1.75      1998-09-04
Hot Mustard                    73        0.95      0.97      1998-05-25
================ END tquery4 OUTPUT ================

---------------- BEGIN resetdb OUTPUT ----------------
Connecting to database server...
Dropping existing sample data tables...
Creating stock table...
Populating stock table...inserted 4 rows.
Creating empty images table...
Creating deadlock testing tables...
Reinitialized sample database successfully.
================ END resetdb OUTPUT ================

---------------- BEGIN ssqls1 OUTPUT ----------------
We have:
	Nürnberger Brats
	Pickle Relish
	Hot Mustard (good American yellow mustard, not that European stuff)
	Hotdog Buns
================ END ssqls1 OUTPUT ================

---------------- BEGIN ssqls2 OUTPUT ----------------
Query: INSERT INTO `stock` (`item`,`num`,`weight`,`price`,`sDate`,`description`) VALUES ('Hot Dogs',100,1.5,NULL,'1998-09-25',NULL)
Query: select * from stock
Records found: 5

Item                           Num       Weight    Price     Date

Nürnberger Brats              97        1.5       8.79      2005-03-10
Pickle Relish                  87        1.5       1.75      1998-09-04
Hot Mustard                    73        0.95      0.97      1998-05-25
Hotdog Buns                    65        1.1       1.1       1998-04-23
Hot Dogs                       100       1.5       (NULL)    1998-09-25
================ END ssqls2 OUTPUT ================

---------------- BEGIN ssqls3 OUTPUT ----------------
Query: UPDATE `stock` SET `item` = 'Nuerenberger Bratwurst',`num` = 97,`weight` = 1.5,`price` = 8.7899999999999991,`sDate` = '2005-03-10',`description` = NULL WHERE `item` = 'Nürnberger Brats'
Query: select * from stock
Records found: 5

Item                           Num       Weight    Price     Date

Nuerenberger Bratwurst         97        1.5       8.79      2005-03-10
Pickle Relish                  87        1.5       1.75      1998-09-04
Hot Mustard                    73        0.95      0.97      1998-05-25
Hotdog Buns                    65        1.1       1.1       1998-04-23
Hot Dogs                       100       1.5       (NULL)    1998-09-25
================ END ssqls3 OUTPUT ================

---------------- BEGIN ssqls4 OUTPUT ----------------
Records found: 5

Item                           Num       Weight    Price     Date

Hot Dogs                       100       1.5       (NULL)    1998-09-25
Hot Mustard                    73        0.95      0.97      1998-05-25
Hotdog Buns                    65        1.1       1.1       1998-04-23
Nuerenberger Bratwurst         97        1.5       8.79      2005-03-10
Pickle Relish                  87        1.5       1.75      1998-09-04

Currently 65 hotdog buns in stock.
================ END ssqls4 OUTPUT ================

---------------- BEGIN ssqls5 OUTPUT ----------------
Custom query:
select * from stock where `weight` = 1.5 and `price` = 8.7899999999999991
================ END ssqls5 OUTPUT ================

---------------- BEGIN ssqls6 OUTPUT ----------------
Query: select * from stock
Records found: 26

Item                           Num       Weight    Price     Date

Tiny Screws                    1000      0.01      0.05      2008-11-11
Needle-nose Pliers             50        0.5       5.95      2008-11-12
Small Soldering Iron           40        0.5       15.95     2008-09-01
Large Soldering Iron           35        0.75      24.95     2008-08-01
Solder Wick                    100       0.1       2.95      2008-04-01
Mini Screwdrivers, 3 pc.       30        0.4       8.95      2008-03-25
Mini Screwdrivers, 6 pc.       40        0.6       12.95     2008-04-01
Wire-wrapping Tool             25        0.2       4.95      2008-04-23
Red LED, 5mm, 3000mcd          300       0.01      0.29      2008-10-02
Orange LED, 5mm, 2500mcd       250       0.01      0.29      2008-07-31
Yellow LED, 5mm, 3000mcd       400       0.01      0.25      2008-09-30
Green LED, 5mm, 1000mcd        350       0.01      0.45      2008-09-27
Blue LED, 5mm, 3900mcd         500       0.01      0.34      2007-12-01
White LED, 5mm, 15000mcd       750       0.01      0.43      2008-02-01
AA Battery, single             220       0.05      0.5       2007-09-19
AA Battery, 4-pack             60        0.2       1.79      2007-08-03
AA Battery, 24-pack            8         1.2       9.99      2007-04-25
C Battery, single              100       0.075     0.65      2007-11-14
C Battery, 4-pack              25        0.3       2.29      2007-06-05
C Battery, 24-pack             5         1.8       10.99     2007-06-13
D Battery, single              180       0.08      0.7       2007-12-03
D Battery, 4-pack              45        0.3       2.59      2007-04-01
D Battery, 24-pack             12        1.9       11.99     2007-05-15
9-volt Battery, single         90        0.06      0.75      2008-01-02
9-volt Battery, 3-pack         17        0.2       1.99      2008-02-28
9-volt Batter, 20-pack         12        1.2       12.99     2007-12-28
================ END ssqls6 OUTPUT ================

---------------- BEGIN load_jpeg OUTPUT ----------------
Inserted "NULL" into images table, 0 bytes, ID 1


================ END load_jpeg OUTPUT ================

---------------- BEGIN cgi_jpeg OUTPUT ----------------
Content-type: text/plain

No image content!
================ END cgi_jpeg OUTPUT ================


--- BEGIN ssqlsxlat -i examples/common.ssqls -o ERROR OUTPUT ---
==== END ssqlsxlat -i examples/common.ssqls -o ERROR OUTPUT ====
--- BEGIN ssqlsxlat -i examples/stock.ssqls -o ERROR OUTPUT ---
==== END ssqlsxlat -i examples/stock.ssqls -o ERROR OUTPUT ====
--- BEGIN ssqlsxlat -i test/test1.ssqls -o ERROR OUTPUT ---
==== END ssqlsxlat -i test/test1.ssqls -o ERROR OUTPUT ====
--- BEGIN ssqlsxlat -i test/test2.ssqls -o ERROR OUTPUT ---
==== END ssqlsxlat -i test/test2.ssqls -o ERROR OUTPUT ====

Changes to lib/field_types.h.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
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





56








57




58





























59
60



61
62


63



64






















65
66



















































































































67
68




69



















70
71
72

73







74





























75

76




77



78


79
80
































































81
82
83
84
/// \file field_types.h
/// \brief Declares a class to hold a list of SQL field type info.

/***********************************************************************
 Copyright (c) 1998 by Kevin Atkinson, (c) 1999, 2000 and 2001 by
 MySQL AB, and (c) 2004-2007 by Educational Technology Resources, Inc.
 Others may also hold copyrights on code in this file.  See the CREDITS
 file in the top directory of the distribution for details.

 This file is part of MySQL++.

 MySQL++ is free software; you can redistribute it and/or modify it
 under the terms of the GNU Lesser General Public License as published
 by the Free Software Foundation; either version 2.1 of the License, or
 (at your option) any later version.

 MySQL++ is distributed in the hope that it will be useful, but WITHOUT
 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
 License for more details.

 You should have received a copy of the GNU Lesser General Public
 License along with MySQL++; if not, write to the Free Software
 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
 USA
***********************************************************************/

#ifndef MYSQLPP_FIELD_TYPES_H
#define MYSQLPP_FIELD_TYPES_H

#include "type_info.h"

#include <vector>

namespace mysqlpp {


#if !defined(DOXYGEN_IGNORE)















// Make Doxygen ignore this

class MYSQLPP_EXPORT ResultBase;




#endif





















































/// \brief A vector of SQL field types.




class FieldTypes : public std::vector<mysql_type_info>


{
public:














	/// \brief Default constructor
	FieldTypes() { }
















































	














	/// \brief Create list of field types from a result set
	FieldTypes(const ResultBase* res)


	{


		init(res);
	}










































































	/// \brief Create fixed-size list of uninitialized field types





	FieldTypes(int i) :








	std::vector<mysql_type_info>(i)




	{





























	}




	/// \brief Initialize field list based on a result set
	FieldTypes& operator =(const ResultBase* res)


	{



		init(res);






















		return *this;
	}




















































































































	/// \brief Insert a given number of uninitialized field type




	/// objects at the beginning of the list



















	///
	/// \param i number of field type objects to insert
	FieldTypes& operator =(int i)

	{







		insert(begin(), i, mysql_type_info());





























		return *this;

	}








private:


	void init(const ResultBase* res);
};

































































} // end namespace mysqlpp

#endif
|
|

<
|
|
|
|



















|
<

|
|
|



>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
|
>
>
>
>

>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
|
>
>
>
>
|
>
>
|
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
|
>
>
|
>
>
|
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
>
>
>
>
|
>
>
>
>
>
>
>
>
|
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>


>
>
>
|
|
>
>
|
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
<
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
|
|
>
|
>
>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
|
>
>
>
>
|
>
>
>
|
>
>
|
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>



<
1
2
3

4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27

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
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
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
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
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
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
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
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
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
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488

489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637

/***********************************************************************
 query.cpp - Implements the Query class.


 Copyright (c) 1998 by Kevin Atkinson, (c) 1999-2001 by MySQL AB, and
 (c) 2004-2008 by Educational Technology Resources, Inc.  Others may
 also hold copyrights on code in this file.  See the CREDITS file in
 the top directory of the distribution for details.

 This file is part of MySQL++.

 MySQL++ is free software; you can redistribute it and/or modify it
 under the terms of the GNU Lesser General Public License as published
 by the Free Software Foundation; either version 2.1 of the License, or
 (at your option) any later version.

 MySQL++ is distributed in the hope that it will be useful, but WITHOUT
 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
 License for more details.

 You should have received a copy of the GNU Lesser General Public
 License along with MySQL++; if not, write to the Free Software
 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
 USA
***********************************************************************/

#include "query.h"


#include "autoflag.h"
#include "dbdriver.h"
#include "connection.h"

namespace mysqlpp {

Query::Query(Connection* c, bool te, const char* qstr) :
#if defined(MYSQLPP_HAVE_STD__NOINIT)
// prevents a double-init memory leak in native VC++ RTL (not STLport!)
std::ostream(std::_Noinit), 
#else
std::ostream(0),
#endif
OptionalExceptions(te),
template_defaults(this),
conn_(c),
copacetic_(true)
{
	init(&sbuffer_);
	if (qstr) {
		sbuffer_.str(qstr);
	}
}

Query::Query(const Query& q) :
#if defined(MYSQLPP_HAVE_STD__NOINIT)
// ditto above
std::ostream(std::_Noinit),
#else
std::ostream(0),
#endif
OptionalExceptions(q.throw_exceptions()),
template_defaults(q.template_defaults),
conn_(q.conn_),
copacetic_(q.copacetic_)
{
	// We don't copy stream buffer or template query stuff from the other
	// Query on purpose.  This isn't a copy ctor so much as a way to
	// ensure that "Query q(conn.query());" works correctly.
	init(&sbuffer_);
}


ulonglong
Query::affected_rows()
{
	return conn_->driver()->affected_rows();
}


int
Query::errnum() const
{
	return conn_->errnum();
}


const char* 
Query::error() const
{
	return conn_->error();
}


size_t
Query::escape_string(std::string* ps, const char* original,
		size_t length) const
{
	if (ps == 0) {
		// Can't do any real work!
		return 0;
	}
	else if (original == 0) {
		// ps must point to the original data as well as to the
		// receiving string, so get the pointer and the length from it.
		original = ps->data();
		length = ps->length();
	}
	else if (length == 0) {
		// We got a pointer to a C++ string just for holding the result
		// and also a C string pointing to the original, so find the
		// length of the original.
		length = strlen(original);
	}

	char* escaped = new char[length * 2 + 1];
	length = escape_string(escaped, original, length);
	ps->assign(escaped, length);
	delete[] escaped;

	return length;
}


size_t
Query::escape_string(char* escaped, const char* original,
		size_t length) const
{
	if (conn_ && *conn_) {
		// Normal case
		return conn_->driver()->escape_string(escaped, original, length);
	}
	else {
		// Should only happen in test/test_manip.cpp, since it doesn't
		// want to open a DB connection just to test the manipulators.
		return DBDriver::escape_string_no_conn(escaped, original, length);
	}
}


bool
Query::exec(const std::string& str)
{
	if ((copacetic_ = conn_->driver()->execute(str.data(),
			static_cast<unsigned long>(str.length()))) == true) {
		if (parse_elems_.size() == 0) {
			// Not a template query, so auto-reset
			reset();
		}
		return true;
	}
	else if (throw_exceptions()) {
		throw BadQuery(error(), errnum());
	}
	else {
		return false;
	}
}


SimpleResult
Query::execute(SQLQueryParms& p)
{
	AutoFlag<> af(template_defaults.processing_);
	return execute(str(p));
}


SimpleResult
Query::execute(const SQLTypeAdapter& s)
{
	if ((parse_elems_.size() == 2) && !template_defaults.processing_) {
		// We're a template query and this isn't a recursive call, so
		// take s to be a lone parameter for the query.  We will come
		// back in here with a completed query, but the processing_
		// flag will be set, allowing us to avoid an infinite loop.
		AutoFlag<> af(template_defaults.processing_);
		return execute(SQLQueryParms() << s);
	}
	else {
		// Take s to be the entire query string
		return execute(s.data(), s.length());
	}
}


SimpleResult
Query::execute(const char* str, size_t len)
{
	if ((copacetic_ = conn_->driver()->execute(str, len)) == true) {
		if (parse_elems_.size() == 0) {
			// Not a template query, so auto-reset
			reset();
		}
		return SimpleResult(conn_, insert_id(), affected_rows(), info());
	}
	else if (throw_exceptions()) {
		throw BadQuery(error(), errnum());
	}
	else {
		return SimpleResult();
	}
}


std::string
Query::info()
{
	return conn_->driver()->query_info();
}


ulonglong
Query::insert_id()
{
	return conn_->driver()->insert_id();
}


bool 
Query::more_results()
{
	return conn_->driver()->more_results();
}


Query&
Query::operator=(const Query& rhs)
{
	set_exceptions(rhs.throw_exceptions());
	template_defaults = rhs.template_defaults;
	conn_ = rhs.conn_;
	copacetic_ = rhs.copacetic_;

	return *this;
}

Query::operator Query::private_bool_type() const
{
	return *conn_ && copacetic_ ? &Query::copacetic_ : 0;
}


void
Query::parse()
{
	std::string str = "";
	char num[4];
	std::string name;

	char* s = new char[sbuffer_.str().size() + 1];
	memcpy(s, sbuffer_.str().data(), sbuffer_.str().size()); 
	s[sbuffer_.str().size()] = '\0';
	const char* s0 = s;

	while (*s) {
		if (*s == '%') {
			// Following might be a template parameter declaration...
			s++;
			if (*s == '%') {
				// Doubled percent sign, so insert literal percent sign.
				str += *s++;
			}
			else if (isdigit(*s)) {
				// Number following percent sign, so it signifies a
				// positional parameter.  First step: find position
				// value, up to 3 digits long.
				num[0] = *s;
				s++;
				if (isdigit(*s)) {
					num[1] = *s;
					num[2] = 0;
					s++;
					if (isdigit(*s)) {
						num[2] = *s;
						num[3] = 0;
						s++;
					}
					else {
						num[2] = 0;
					}
				}
				else {
					num[1] = 0;
				}
				signed char n = atoi(num);

				// Look for option character following position value.
				char option = ' ';
				if (*s == 'q' || *s == 'Q') {
					option = *s++;
				}

				// Is it a named parameter?
				if (*s == ':') {
					// Save all alphanumeric and underscore characters
					// following colon as parameter name.
					s++;
					for (/* */; isalnum(*s) || *s == '_'; ++s) {
						name += *s;
					}

					// Eat trailing colon, if it's present.
					if (*s == ':') {
						s++;
					}

					// Update maps that translate parameter name to
					// number and vice versa.
					if (n >= static_cast<short>(parsed_names_.size())) {
						parsed_names_.insert(parsed_names_.end(),
								static_cast<std::vector<std::string>::size_type>(
										n + 1) - parsed_names_.size(),
								std::string());
					}
					parsed_names_[n] = name;
					parsed_nums_[name] = n;
				}

				// Finished parsing parameter; save it.
				parse_elems_.push_back(SQLParseElement(str, option, n));
				str = "";
				name = "";
			}
			else {
				// Insert literal percent sign, because sign didn't
				// precede a valid parameter string; this allows users
				// to play a little fast and loose with the rules,
				// avoiding a double percent sign here.
				str += '%';
			}
		}
		else {
			// Regular character, so just copy it.
			str += *s++;
		}
	}

	parse_elems_.push_back(SQLParseElement(str, ' ', -1));
	delete[] s0;
}


SQLTypeAdapter*
Query::pprepare(char option, SQLTypeAdapter& S, bool replace)
{
	if (S.is_processed()) {
		return &S;
	}

	if (option == 'q') {
		std::string temp(S.quote_q() ? "'" : "", S.quote_q() ? 1 : 0);

		if (S.escape_q()) {
			char *escaped = new char[S.size() * 2 + 1];
			size_t len = conn_->driver()->escape_string(escaped,
					S.data(), static_cast<unsigned long>(S.size()));
			temp.append(escaped, len);
			delete[] escaped;
		}
		else {
			temp.append(S.data(), S.length());
		}

		if (S.quote_q()) temp.append("'", 1);

		SQLTypeAdapter* ss = new SQLTypeAdapter(temp);

		if (replace) {
			S = *ss;
			S.set_processed();
			delete ss;
			return &S;
		}
		else {
			return ss;
		}
	}
	else if (option == 'Q' && S.quote_q()) {
		std::string temp("'", 1);
		temp.append(S.data(), S.length());
		temp.append("'", 1);
		SQLTypeAdapter *ss = new SQLTypeAdapter(temp);

		if (replace) {
			S = *ss;
			S.set_processed();
			delete ss;
			return &S;
		}
		else {
			return ss;
		}
	}
	else {
		if (replace) {
			S.set_processed();
		}
		return &S;
	}
}


void
Query::proc(SQLQueryParms& p)
{
	sbuffer_.str("");

	for (std::vector<SQLParseElement>::iterator i = parse_elems_.begin();
			i != parse_elems_.end(); ++i) {
		MYSQLPP_QUERY_THISPTR << i->before;
		int num = i->num;
		if (num >= 0) {
			SQLQueryParms* c;
			if (size_t(num) < p.size()) {
				c = &p;
			}
			else if (size_t(num) < template_defaults.size()) {
				c = &template_defaults;
			}
			else {
				*this << " ERROR";
				throw BadParamCount(
						"Not enough parameters to fill the template.");
			}

			SQLTypeAdapter& param = (*c)[num];
			SQLTypeAdapter* ss = pprepare(i->option, param, c->bound());
			MYSQLPP_QUERY_THISPTR << *ss;
			if (ss != &param) {
				// pprepare() returned a new string object instead of
				// updating param in place, so we need to delete it.
				delete ss;
			}
		}
	}
}


void
Query::reset()
{
	seekp(0);
	clear();
	sbuffer_.str("");

	parse_elems_.clear();
	template_defaults.clear();
}


StoreQueryResult
Query::store(SQLQueryParms& p)
{
	AutoFlag<> af(template_defaults.processing_);
	return store(str(p));
}


StoreQueryResult 
Query::store(const SQLTypeAdapter& s)
{
	if ((parse_elems_.size() == 2) && !template_defaults.processing_) {
		// We're a template query and this isn't a recursive call, so
		// take s to be a lone parameter for the query.  We will come
		// back in here with a completed query, but the processing_
		// flag will be set, allowing us to avoid an infinite loop.
		AutoFlag<> af(template_defaults.processing_);
		return store(SQLQueryParms() << s);
	}
	else {
		// Take s to be the entire query string
		return store(s.data(), s.length());
	}
}


StoreQueryResult
Query::store(const char* str, size_t len)
{
	MYSQL_RES* res = 0;
	if ((copacetic_ = conn_->driver()->execute(str, len)) == true) {
		res = conn_->driver()->store_result();
	}

	if (res) {
		if (parse_elems_.size() == 0) {
			// Not a template query, so auto-reset
			reset();
		}

		return StoreQueryResult(res, conn_->driver(), throw_exceptions());
	}
	else {
		// Either result set is empty (which is copacetic), or there
		// was a problem returning the result set (which is not).  If
		// caller knows the result set will be empty (e.g. query is
		// INSERT, DELETE...) it should call exec{ute}() instead, but
		// there are good reasons for it to be unable to predict this.
		copacetic_ = conn_->driver()->result_empty();
		if (copacetic_) {
			if (parse_elems_.size() == 0) {
				// Not a template query, so auto-reset
				reset();
			}
			return StoreQueryResult();
		}
		else if (throw_exceptions()) {
			throw BadQuery(error(), errnum());
		}
		else {
			return StoreQueryResult();
		}
	}
}


StoreQueryResult
Query::store_next()
{
#if MYSQL_VERSION_ID > 41000		// only in MySQL v4.1 +
	DBDriver::nr_code rc = conn_->driver()->next_result();
	if (rc == DBDriver::nr_more_results) {
		// There are more results, so return next result set.
		MYSQL_RES* res = conn_->driver()->store_result();
		if (res) {
			return StoreQueryResult(res, conn_->driver(),
					throw_exceptions());
		} 
		else {
			// Result set is null, but throw an exception only i it is
			// null because of some error.  If not, it's just an empty
			// result set, which is harmless.  We return an empty result
			// set if exceptions are disabled, as well.
			if (conn_->errnum() && throw_exceptions()) {
				throw BadQuery(error(), errnum());
			} 
			else {
				return StoreQueryResult();
			}
		}
	}
	else if (throw_exceptions()) {
        if (rc == DBDriver::nr_error) {
            throw BadQuery(error(), errnum());
        }
		else if (conn_->errnum()) {
			throw BadQuery(error(), errnum());
        }
		else {
			return StoreQueryResult();	// normal end-of-result-sets case
		}
    }
    else {
        return StoreQueryResult();
	}
#else
	return store();
#endif // MySQL v4.1+
}


std::string
Query::str(SQLQueryParms& p)
{
	if (!parse_elems_.empty()) {
		proc(p);
	}

	return sbuffer_.str();
}


UseQueryResult
Query::use(SQLQueryParms& p)
{
	AutoFlag<> af(template_defaults.processing_);
	return use(str(p));
}


UseQueryResult
Query::use(const SQLTypeAdapter& s)
{
	if ((parse_elems_.size() == 2) && !template_defaults.processing_) {
		// We're a template query and this isn't a recursive call, so
		// take s to be a lone parameter for the query.  We will come
		// back in here with a completed query, but the processing_
		// flag will be set, allowing us to avoid an infinite loop.
		AutoFlag<> af(template_defaults.processing_);
		return use(SQLQueryParms() << s);
	}
	else {
		// Take s to be the entire query string
		return use(s.data(), s.length());
	}
}


UseQueryResult
Query::use(const char* str, size_t len)
{
	MYSQL_RES* res = 0;
	if ((copacetic_ = conn_->driver()->execute(str, len)) == true) {
		res = conn_->driver()->use_result();
	}

	if (res) {
		if (parse_elems_.size() == 0) {
			// Not a template query, so auto-reset
			reset();
		}
		return UseQueryResult(res, conn_->driver(), throw_exceptions());
	}
	else {
		// Either result set is empty (which is copacetic), or there
		// was a problem returning the result set (which is not).  If
		// caller knows the result set will be empty (e.g. query is
		// INSERT, DELETE...) it should call exec{ute}() instead, but
		// there are good reasons for it to be unable to predict this.
		copacetic_ = conn_->driver()->result_empty();
		if (copacetic_) {
			if (parse_elems_.size() == 0) {
				// Not a template query, so auto-reset
				reset();
			}
			return UseQueryResult();
		}
		else if (throw_exceptions()) {
			throw BadQuery(error(), errnum());
		}
		else {
			return UseQueryResult();
		}
	}
}


} // end namespace mysqlpp


Changes to lib/insertpolicy.h.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
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
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108

109
110
111
112
113
114

115
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
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
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
/// \file insertpolicy.h
/// \brief Declares the InsertPolicy classes.
///
/// One creates an insert policy object to control how
/// Query::insertfrom() builds queries from collections of SSQLS
/// objects.  Policy objects are what cause Query::insertfrom() to
/// have different insertion behavior than Query::insert(iter, iter)
///
/// These templates use a class called the AccessController, which
/// is a stand-in for the mysqlpp::Transaction class and defaults to 
/// the Transaction class.  Since some of the InsertPolicy objects
/// (SizeThresholdInsertPolicy and MaxPacketInsertPolicy) may cause 
/// Query::insertfrom() to issue multiple SQL statements to perform
/// the insertion of all the objects in the container, and a failure in
/// one of these statements would leave the table in an indeterminate
/// state, the whole operation is wrapped in a transaction.
///
/// However, a transaction may not be desired if the calling code
/// is managing transactions, or transactions are not being used for 
/// some other reason.  In this case, the template can be instantiated
/// with the NoTransaction class.  It provides the complete Transaction
/// class interface, while doing nothing.
///
/// Where possible, you should use one of the provided insert
/// policy classes, but you can define your own if you need a behavior
/// that the provided set doesn't include.
/// 
/// This file is not meant to be included in end-user code.  It's
/// included in Query's public interface, since it is only used with
/// Query::insertfrom().  You access it as Query::InsertPolicy<T>

/***********************************************************************
 Copyright © 2008-2009 by AboveNet, Inc., and © 2009 by Educational
 Technology Resources, Inc.  Others may also hold copyrights on code
 in this file.  See the CREDITS file in the top directory of the
 distribution for details.

 This file is part of MySQL++.

 MySQL++ is free software; you can redistribute it and/or modify it
 under the terms of the GNU Lesser General Public License as published
 by the Free Software Foundation; either version 2.1 of the License, or
 (at your option) any later version.

 MySQL++ is distributed in the hope that it will be useful, but WITHOUT
 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
 License for more details.

 You should have received a copy of the GNU Lesser General Public
 License along with MySQL++; if not, write to the Free Software
 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
 USA
***********************************************************************/

#if !defined(MYSQLPP_INSERTPOLICY_H)
#define MYSQLPP_INSERTPOLICY_H

// Only allow these templates to be defined if they're being bodily
// included into class Query's definition.  They're in this separate
// file only for claity, so they don't get lost among the other
// definitions in class Query.  Without this, Doxygen will pick them
// up and treat them as a) outside namespace mysqlpp; and b) not member
// templates of class Query.  We also don't want end-users of the
// library to #include this file in their own code; these templates
// should only be used as mysqlpp::Query::*.
#if defined(MYSQLPP_DEFINE_INSERT_POLICY_TEMPLATES)


/// \brief An insert policy object that triggers a new INSERT
/// statement after a given number of rows have been inserted.
///
/// This policy is very lightweight, but is only reliable when you
/// can predict the size of each INSERT in advance.  The others do
/// more processing to reduce the risk of unpredictable row sizes.
template <class AccessController = Transaction>
class MYSQLPP_EXPORT RowCountInsertPolicy
{
public:
	/// \brief Constructor
	RowCountInsertPolicy(unsigned int rows) :
	cur_rows_(0),
	max_rows_(rows)
	{
	}

	/// \brief Destructor
	~RowCountInsertPolicy() { }

	/// \brief Can we add another object to the query?
	///
	/// \retval true if the object is allowed to be added to the
	/// INSERT statement
	template <class RowT>
	bool can_add(int, const RowT&)
	{
		if (++cur_rows_ > max_rows_) {
			cur_rows_ = 0;
			return false;
		}
		else {
			return true;
		}
	}

	/// \brief Alias for our access controller type
	typedef AccessController access_controller;


private:
	unsigned int cur_rows_;
	unsigned const int max_rows_;
};



/// \brief An insert policy object that triggers a new INSERT statement
/// after a size threshold for the length of the INSERT statement
/// is exceeded.
///
/// Although this insert policy isn't completely deterministic, it
/// avoids building the VALUES expression for the SSQLS object
/// passed in.
template <class AccessController = Transaction>
class MYSQLPP_EXPORT SizeThresholdInsertPolicy
{
public:
	/// \brief Constructor
	SizeThresholdInsertPolicy(int size) :
	size_(size)
	{
	}

	/// \brief Destructor
	~SizeThresholdInsertPolicy() { }

	/// \brief Can we add another object to the query?
	///
	/// \param size current length of the INSERT statement
	/// \param object the SSQLS object to be added
	///
	/// \retval true if the object is allowed to be added to the
	/// INSERT statement
	template <class RowT>
	bool can_add(int size, const RowT& object) const
	{
		(void)object;		// we don't use this, but other policies do
		return (size < size_);
	}

	/// \brief Alias for our access controller type
	typedef AccessController access_controller;

private:
	int size_;
};


/// \brief An insert policy object that triggers a new INSERT statement
/// if the object to be added would cause the statement to exceed
/// a maximum size.
///
/// This differs from the SizeThresholdInsertPolicy in that it builds
/// the VALUES expression and checks whether it would cause the
/// length of the INSERT statement to exceed the maximum size.
template <class AccessController = Transaction>
class MYSQLPP_EXPORT MaxPacketInsertPolicy
{
public:
	/// \brief Constructor
	///
	/// \param con connection object used for escaping text
	/// \param size the maximum allowed size for an INSERT

	///     statement
	MaxPacketInsertPolicy(Connection* con, int size) :
	conn_(con), size_(size)
	{
	}

	/// \brief Constructor
	///
	/// This version does not use a Connection* so it will not be
	/// able to take the character set into account when escaping
	/// the text.
	///
	/// \param size the maximum allowed size for an INSERT
	///     statement
	MaxPacketInsertPolicy(int size) :
	conn_(0), size_(size)
	{
	}

	/// \brief Destructor
	~MaxPacketInsertPolicy() { }

	/// \brief Can we add another object to the query?
	///
	/// \param size current length of the INSERT statement
	/// \param object the SSQLS object to be added
	///
	/// \retval true if the object is allowed to be added to the
	///     INSERT statement
	template <class RowT>
	bool can_add(int size, const RowT& object) const
	{
		if (size < size_) {
			// Haven't hit size threshold yet, so see if this next
			// item pushes it over the line.
			SQLStream s(conn_);
			s << ",(" << object.value_list() << ")";
			return (size_ - size) >= static_cast<int>(s.str().size());
		}
		else {
			// Already too much in query buffer!
			return false;
		}
	}

	/// \brief Alias for our access controller type
	typedef AccessController access_controller;

private:
	Connection* conn_;
	int size_;
};

#endif // defined(MYSQLPP_DEFINE_INSERT_POLICY_TEMPLATES)

#endif // !defined(MYSQLPP_INSERTPOLICY_H)

<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
|
<
<
<
<
<
|
<
|
<
<
<
<
|
<
<
<
<
<
<
<
<
<
<
<
<
<

<
<
<
<
<
<
<
<
<
|
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
|
<
<
|
<
<
<
<
<
<
<
|
<
<
<
|
<
<
<
|
<
<
|
>
|
<
<
<
|
|
>
<
<
<
<
<
<
<
<
<
<
<
<
<
|
<
<
|
<
<
|
<
<
<
<
<
<
<
<
<
<
<
<
<
|
<
<
|
<
<
<
|
|
<
<
|
<
<
<
<
<
<
<
<
<
<
<
<
>
|
<
<
<
<
|
<
<
<
<
|
<
<
<
<
<
<
<
|
<
<
|
<
<
<
<
<
<
<
<
<
<
|
<
<
<
<
<
<
|
<
<
<
<
|
<
<
|
<
<
<
<
|
<
|
<
|






























1





2

3




4













5









6
7
















8


9







10



11



12


13
14
15



16
17
18













19


20


21













22


23



24
25


26












27
28




29




30







31


32










33






34




35


36




37

38

39






























#!/bin/bash





AHCMD=/usr/XSLFormatterV42/run.sh

FOPCMD=$(type -p fop)




XEPCMD=/usr/local/xep/xep























FOFILE=$1
PDFFILE=$2
















if [ -n "$FOFILE" -a -r "$FOFILE" -a -n "$PDFFILE" ]


then







	if [ -x "$XEPCMD" ]



	then



		echo Rendering $FOFILE to $PDFFILE with RenderX XEP...


		$XEPCMD -quiet -fo $FOFILE -pdf $PDFFILE
	elif [ -x "$AHCMD" ]
	then



		echo Rendering $FOFILE to $PDFFILE with Antenna House XSL Formatter...
		$AHCMD -silent -d $FOFILE -o $PDFFILE
	elif [ -x "$FOPCMD" ]













	then


		echo "Rendering $FOFILE to $PDFFILE with Apache FOP ($FOPCMD)..."


		$FOPCMD -q -fo $FOFILE $PDFFILE













	else


		echo 'Cannot find a working XSL-FO processor on your system!  See'



		echo 'doc/usrman/README.txt for instructions on installing one.'
		echo


		exit 1












	fi
else




	if [ -n "$FOFILE" ]




	then







		echo "XSL-FO file $FOFILE does not exist."


		echo










	fi






	echo "usage: $0 fofile pdffile"




	echo


	echo '    Translates XSL-FO in fofile to PDF output in pdffile.'




	echo

	exit 1

fi

Changes to lib/manip.cpp.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
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
56

57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
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
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
191
192
193
194
195
196
197
198
199
200
201
202

203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
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
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284

/***********************************************************************
 manip.cpp - Implements MySQL++'s various quoting/escaping stream
	manipulators.

 Copyright (c) 1998 by Kevin Atkinson, (c) 1999-2001 by MySQL AB, and
 (c) 2004-2007 by Educational Technology Resources, Inc.  Others may
 also hold copyrights on code in this file.  See the CREDITS.txt file
 in the top directory of the distribution for details.

 This file is part of MySQL++.

 MySQL++ is free software; you can redistribute it and/or modify it
 under the terms of the GNU Lesser General Public License as published
 by the Free Software Foundation; either version 2.1 of the License, or
 (at your option) any later version.

 MySQL++ is distributed in the hope that it will be useful, but WITHOUT
 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
 License for more details.

 You should have received a copy of the GNU Lesser General Public
 License along with MySQL++; if not, write to the Free Software
 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
 USA
***********************************************************************/

#include "manip.h"

#include "query.h"
#include "sqlstream.h"

using namespace std;

namespace mysqlpp {

SQLQueryParms&
operator <<(quote_type2 p, SQLTypeAdapter& in)
{
	if (in.quote_q()) {
		string temp("'", 1), escaped;
		p.qparms->escape_string(&escaped, in.data(), in.length());
		temp.append(escaped);
		temp.append("'", 1);
		*p.qparms << SQLTypeAdapter(temp, true);
		return *p.qparms;

	}
	else {
		in.set_processed();
		return *p.qparms << in;
	}
}


ostream&
operator <<(quote_type1 o, const SQLTypeAdapter& in)

{
	Query* pq = dynamic_cast<Query*>(o.ostr);

	// If it's not a Query*, maybe it's a SQLStream*.
	SQLStream* psqls = pq ? 0 : dynamic_cast<SQLStream*>(o.ostr);

	// If it's a Query or a SQLStream, we'll be using unformatted output.
	if (pq || psqls) {
		if (in.quote_q()) o.ostr->put('\'');

		// Now, is escaping appropriate for source data type of 'in'?
		if (in.escape_q()) {
			string escaped;

			// If it's not a Query*, then it has to be a SQLStream.
			if (pq) {
				pq->escape_string(&escaped, in.data(), in.length());
			}
			else {
				psqls->escape_string(&escaped, in.data(), in.length());
			}

			o.ostr->write(escaped.data(), escaped.length());
		}
		else {
			o.ostr->write(in.data(), in.length());
		}

		if (in.quote_q()) o.ostr->put('\'');
	}
	else {
		// Some other stream type, so use formatted output.  User
		// shouldn't be trying to use the quote manipulator, but
		// that's no reason to break their formatting.
		*o.ostr << string(in.data(), in.length());
	}

	return *o.ostr;
}


ostream&
operator <<(quote_only_type1 o, const SQLTypeAdapter& in)
{
	Query* pq = dynamic_cast<Query*>(o.ostr);

	// If it's not a Query*, maybe it's a SQLStream*.
	SQLStream* psqls = pq ? 0 : dynamic_cast<SQLStream*>(o.ostr);

	// If it's a Query or SQLStream, use unformatted output
	if (pq || psqls) {
		if (in.quote_q()) o.ostr->put('\'');

		o.ostr->write(in.data(), in.length());

		if (in.quote_q()) o.ostr->put('\'');
	}
	else {
		// Some other stream type, so use formatted output.  User
		// shouldn't be trying to use this manipulator on a non-Query
		// stream, but that's no reason to break their formatting.
		*o.ostr << '\'' << in << '\'';
	}

	return *o.ostr;
}


ostream&
operator <<(ostream& o, const SQLTypeAdapter& in)
{
	if (dynamic_cast<Query*>(&o) || dynamic_cast<SQLStream*>(&o)) {
		// It's a Query or a SQLStream, so use unformatted output.
		return o.write(in.data(), in.length());
	}
	else {
		// Some other stream type, so use formatted output.  We do this
		// through the temporary so we remain null-friendly.
		return o << string(in.data(), in.length());
	}
}


SQLQueryParms&
operator <<(quote_only_type2 p, SQLTypeAdapter& in)
{




	if (in.quote_q()) {
		string temp("'", 1);
		temp.append(in.data(), in.length());
		temp.append("'", 1);
		return *p.qparms << SQLTypeAdapter(temp, true);
	}
	else {
		in.set_processed();
		return *p.qparms << in;
	}
}


SQLQueryParms&
operator <<(quote_double_only_type2 p, SQLTypeAdapter& in)
{
	if (in.quote_q()) {

		string temp("\"", 1);
		temp.append(in.data(), in.length());
		temp.append("\"", 1);
		return *p.qparms << SQLTypeAdapter(temp, true);
	}
	else {
		in.set_processed();
		return *p.qparms << in;
	}
}


ostream&
operator <<(quote_double_only_type1 o, const SQLTypeAdapter& in)
{
	Query* pq = dynamic_cast<Query*>(o.ostr);

	// If it's not a Query*, maybe it's a SQLStream*.

	SQLStream* psqls = pq ? 0 : dynamic_cast<SQLStream*>(o.ostr);

	// If it's a Query or a SQLStream, use unformatted output
	if (pq || psqls) {
		if (in.quote_q()) o.ostr->put('"');

		o.ostr->write(in.data(), in.length());
	
		if (in.quote_q()) o.ostr->put('"');
	}
	else {
		// Some other stream type, so use formatted output.  User
		// shouldn't be trying to use this manipulator on a non-Query
		// stream, but that's no reason to break their formatting.
		*o.ostr << '"' << in << '"';
	}

	return *o.ostr;
}


SQLQueryParms&
operator <<(escape_type2 p, SQLTypeAdapter& in)
{
	if (in.escape_q()) {

		string escaped;
		p.qparms->escape_string(&escaped, in.data(), in.length());
		*p.qparms << SQLTypeAdapter(escaped, true);
		return *p.qparms;
	}
	else {
		in.set_processed();
		return *p.qparms << in;
	}
}


ostream&
operator <<(escape_type1 o, const SQLTypeAdapter& in)
{
	Query* pq = dynamic_cast<Query*>(o.ostr);

	// If it's not a Query*, maybe it's a SQLStream*.
	SQLStream* psqls = pq ? 0 : dynamic_cast<SQLStream*>(o.ostr);

	if (pq || psqls) {
		// It's a Query or a SQLStream, so we'll be using unformatted output.
		// Now, is escaping appropriate for source data type of 'in'?
		if (in.escape_q()) {
			string escaped;

			// If it's not a Query*, then it has to be a SQLStream.
			if (pq) {
				pq->escape_string(&escaped, in.data(), in.length());
			}
			else {
				psqls->escape_string(&escaped, in.data(), in.length());
			}

			return o.ostr->write(escaped.data(), escaped.length());
		}
		else {
			// It's not escaped, so just write the unformatted output
			return o.ostr->write(in.data(), in.length());

		}
	}
	else {
		// Some other stream type, so use formatted output.  User
		// shouldn't be trying to use the escape manipulator, but
		// that's no reason to break their formatting.
		return *o.ostr << string(in.data(), in.length());
	}
}


SQLQueryParms&
operator <<(do_nothing_type2 p, SQLTypeAdapter& in)
{
	in.set_processed();
	return *p.qparms << in;
}


ostream&
operator <<(do_nothing_type1 o, const SQLTypeAdapter& in)

{
	if (dynamic_cast<Query*>(o.ostr) || dynamic_cast<SQLStream*>(o.ostr)) {
		// It's a Query or a SQLStream, so use unformatted output
		return o.ostr->write(in.data(), in.length());
	}
	else {
		// Some other stream type, so use formatted output.  User
		// shouldn't be trying to use this manipulator on a non-Query
		// stream, but that's no reason to break their formatting.
		return *o.ostr << in;
	}
}


SQLQueryParms&
operator <<(ignore_type2 p, SQLTypeAdapter& in)
{
	return *p.qparms << in;
}

} // end namespace mysqlpp


<
|
<
|
<
<
<
<
|
|
|
<
<
<
<
|
<
<
<
<

<
<
<
<
<
|
<
|
<
<
|
<
|
<

<
<
|
<
<
<
<
<
<
<
>
|
<
<
<
<
<
|
|
<
<
>
|
<
|
<
<
|
<
<
<
|
<
<
<
|
<
<
<
|
<
<
<
|
<
<
<
<
<
|
<
|
<
<
<
<
<
<
|
<
<
|
|
<
<
|
<
|
<
<
|
<
<
<

<
|
<
<
<
|
<
<
<
<
|
<
|
|
|
<
<
<
<
<
<
<
<
<
<
<
<
<
|
|
|
<
|
>
>
>
>
<
<
<
<
<
|
<
<
<
<
<
|
|
<
<
<
<
>
|
<
<
<
|
<
<
<
<
<
|
|
|
<
|
<
|
<
>
<

<
<
<
|
<
|
<
<
<
<
<
<
<
<
|
<
|
|
|
<
<
|
<
>
|
<
<
<
|
<
<
<
<
<
|

|
<
|
<
|
<
<
|
<
<
<
<
<
|
<
<
<
<
|
<
|
|
<
|
<
<
<
>
|
<
<
<
<
<
<
|
<
|
|
<
<
|
<
<
|
|
|
<
<
>
|
<
<
<
<
<
<
<
<
<
<
<
|

<
<
<
<
<
|
<
|
>

1

2




3
4
5




6




7





8

9


10

11

12


13







14
15





16
17


18
19

20


21



22



23



24



25





26

27






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
56
57

58

59

60

61



62

63








64

65
66
67


68

69
70



71





72
73
74

75

76


77





78




79

80
81

82



83
84






85

86
87


88


89
90
91


92
93











94
95





96

97
98

MySQL++ was created by Kevin Atkinson during 1998.  From version

1.0 (released in June 1999) through 1.7.9 (May 2001), the primary




maintainer was Sinisa Milivojevic <sinisa@mysql.com>.  Neither Kevin
nor Sinisa are currently involved in MySQL++ development.  The current
maintainer is Warren Young <mysqlpp@etr-usa.com>, starting with




version 1.7.10 in August of 2004.










For a fuller account of the library's history, see the first chapter

of the user manual.  For the nitty-gritty details, see the ChangeLog


in the root package directory.  ChangeLog items since 1.7.9 that

aren't attributed to anyone else were done by Warren Young.












Other contributors of note since 1.7.10:






    Chris Frey <cdfrey@foursquare.net>: Lots of GCC warning fixes
    for the bleeding-edge compiler versions, Gentoo ebuild support,


    and misc other fixes.


    Mark Meredino <Mark_Merendino@cnt.com>: Several fixes and


    additions, including a lot of work on Microsoft Visual C++



    compatibility, and discoveries made while spelunking in the



    library.







    Evan Wies <evan@athenacr.com>: Contributed several C++ code





    style cleanups.








    Arnon Jalon <Arnon.Jalon@247RealMedia.com>: Added the multi-query


    result set handling features, and examples/multiquery.cpp to
    demonstrate it.




    Korolyov Ilya has submitted several patches in many different


    areas of the library.





    Remi Collet <Liste@FamilleCollet.com> is maintaining offical RPMs



    for Fedora, with other systems on the way.  His work has improved




    the RPM spec file we distribute greatly.


    Joel Fielder <joel.fielder@switchplane.com> of Switchplane,
    Ltd. created the ScopedConnection class, came up with the original













    idea for Query's for_each() and store_in() methods, provided the
    basis for examples/for_each.cpp, and provided a fix for exception
    flag propagation in Query.


    Jim Wallace <jwallace@kaneva.com> demonstrated the need
    for BadQuery::errnum(), and contributed the patches and also
    examples/deadlock.cpp to test that this feature does what it is
    supposed to.











    Jonathan Wakely <mysql@kayari.org> rebuilt my original versions
    of ConnectionPool, RefCountedPointer, and RefCountedBuffer.




    They're now simpler and safer.  He also created the numeric
    conversion logic in lib/mystring.h introduced in v3.0.









    Rick Gutleber <rgutleber@above.net> contributed the 
    Query::insertfrom() method and associated InsertPolicy object,
    as well as the SQLStream class.



Here are the personal credits from the old 1.7.9 documentation,

apparently written by Kevin Atkinson:





    Chris Halverson - For helping me get it to compile under Solaris.










    Fredric Fredricson - For a long talk about automatic conversions.


    Michael Widenius - MySQL developer who has been very supportive of
        my efforts.




    Paul J. Lucas - For the original idea of treating the query object
        like a stream.









    Scott Barron - For helping me with the shared libraries.

    Jools Enticknap - For giving me the Template Queries idea.



    M. S. Sriram - For a detailed dission of how the Template Queries


        should be implemented, the suggestion to throw exceptions on bad





        queries, and the idea of having a back-end independent query




        object (ie SQLQuery).


    Sinisa Milivojevic - For becoming the new offical maintainer.





    D. Hawkins and E. Loic for their autoconf + automake contribution.









See the ChangeLog for further credits, and details about the differences
between the many versions of this library.






Please do not email any of these people with general questions about
MySQL++. All of us who are still active in MySQL++ development read the


mailing list, so questions sent there do get to us:












    http://lists.mysql.com/plusplus






The mailing list is superior to private email because the answers are

archived for future questioners to find, and because you are likely to
get answers from more people.

Changes to lib/manip.h.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
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
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
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
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
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
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
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
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
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
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
/// \file manip.h
/// \brief Declares the Query stream manipulators and operators.
///
/// These manipulators let you automatically quote elements or escape
/// characters that are special in SQL when inserting them into a
/// Query stream.  They make it easier to build syntactically-correct
/// SQL queries.
///
/// This file also includes special \c operator<< definitions for a few
/// key MySQL++ data types, since we know when to do automatic quoting
/// and escaping for these types.  This only works with Query streams,
/// not regular std::ostreams, since we're only concerned with making
/// correct SQL, not with presentation matters.
///
/// test/test_manip.cpp exercises the mechanisms defined here.

/***********************************************************************
 Copyright (c) 1998 by Kevin Atkinson, (c) 1999-2001 by MySQL AB, and
 (c) 2004-2007 by Educational Technology Resources, Inc.  Others may
 also hold copyrights on code in this file.  See the CREDITS.txt file
 in the top directory of the distribution for details.

 This file is part of MySQL++.

 MySQL++ is free software; you can redistribute it and/or modify it
 under the terms of the GNU Lesser General Public License as published
 by the Free Software Foundation; either version 2.1 of the License, or
 (at your option) any later version.

 MySQL++ is distributed in the hope that it will be useful, but WITHOUT
 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
 License for more details.

 You should have received a copy of the GNU Lesser General Public
 License along with MySQL++; if not, write to the Free Software
 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
 USA
***********************************************************************/

#ifndef MYSQLPP_MANIP_H
#define MYSQLPP_MANIP_H

#include "common.h"

#include "myset.h"
#include "stadapter.h"

#include <iostream>

namespace mysqlpp {

class SQLQueryParms;


/// \enum quote_type0
/// \anchor quote_manip
///
/// The standard 'quote' manipulator.  It is the most widely useful
/// manipulator in MySQL++.
///
/// Insert this manipulator into a Query or SQLQueryParms stream to put
/// single quotes around the next item in the stream, and escape any
/// characters within it that are special in SQL, if the data type of
/// the next item in the stream may require it.  By contrast, Date
/// objects only require escaping, not quoting, and integers never
/// require either.  The manipulators won't do work they know is not
/// necessary to ensure syntactially-correct SQL.

enum quote_type0
{
	quote ///< insert into a Query stream to single-quote and escape next item
};


#if !defined(DOXYGEN_IGNORE)
// Doxygen will not generate documentation for this section.

struct quote_type1
{
	std::ostream * ostr;
	quote_type1(std::ostream * o) :
	ostr(o)
	{
	}
};


inline quote_type1
operator <<(std::ostream& o, quote_type0 /* esc */)
{
	return quote_type1(&o);
}


struct quote_type2
{
	SQLQueryParms *qparms;
	quote_type2(SQLQueryParms* p) :
	qparms(p)
	{
	}
};


inline quote_type2
operator <<(SQLQueryParms& p, quote_type0 /* esc */)
{
	return quote_type2(&p);
}


/// \brief Inserts a SQLTypeAdapter into a stream, quoted and escaped
/// as appropriate to the data type the object was initialized from.

MYSQLPP_EXPORT SQLQueryParms& operator <<(quote_type2 p,
		SQLTypeAdapter& in);


/// \brief Inserts a anything that can be converted to SQLTypeAdapter
/// into a stream, quoted and escaped as needed if it's a Query stream

MYSQLPP_EXPORT std::ostream& operator <<(quote_type1 o,
		const SQLTypeAdapter& in);


/// \brief Inserts a SQLTypeAdapter into a non-Query stream.
///
/// Although we know how to quote and escape SQLTypeAdapter objects, we
/// only do that when inserting them into Query streams or when given an
/// explicit manipulator because this feature is only intended to make
/// it easier to build syntactically-correct SQL queries.

MYSQLPP_EXPORT std::ostream& operator <<(std::ostream& o,
		const SQLTypeAdapter& in);


template <class ST>
inline std::ostream&
operator <<(quote_type1 o, const Set<ST>& in)
{
	return *o.ostr << '\'' << in << '\'';
}

#endif // !defined(DOXYGEN_IGNORE)


/// \enum quote_only_type0
/// \anchor quote_only_manip
///
/// The 'quote_only' manipulator.
///
/// Similar to <a href="#quote_manip">quote manipulator</a>, except that
/// it doesn't escape special SQL characters.

enum quote_only_type0
{
	quote_only				///< insert into a std::ostream to single-quote next item
};


#if !defined(DOXYGEN_IGNORE)
// Doxygen will not generate documentation for this section.

struct quote_only_type1
{
	std::ostream* ostr;
	quote_only_type1(std::ostream* o) :
	ostr(o)
	{
	}
};


inline quote_only_type1
operator <<(std::ostream& o, quote_only_type0 /* esc */)
{
	return quote_only_type1(&o);
}


struct quote_only_type2
{
	SQLQueryParms* qparms;
	quote_only_type2(SQLQueryParms* p) :
	qparms(p)
	{
	}
};


inline quote_only_type2
operator <<(SQLQueryParms& p, quote_only_type0 /* esc */)
{
	return quote_only_type2(&p);
}


/// \brief Inserts a SQLTypeAdapter into a stream, quoting it unless it's
/// data that needs no quoting.
///
/// We make the decision to quote the data based on the in.quote_q()
/// flag.  You can set it yourself, but SQLTypeAdapter's ctors should set
/// it correctly for you.

MYSQLPP_EXPORT SQLQueryParms&
operator <<(quote_only_type2 p, SQLTypeAdapter& in);


MYSQLPP_EXPORT std::ostream&
operator <<(quote_only_type1 o, const SQLTypeAdapter& in);


template <class ST>
inline std::ostream&
operator <<(quote_only_type1 o, const Set<ST>& in)
{
	return *o.ostr << '\'' << in << '\'';
}

#endif // !defined(DOXYGEN_IGNORE)


/// \enum quote_double_only_type0
/// \anchor quote_double_manip
///
/// The 'double_quote_only' manipulator.
///
/// Similar to <a href="#quote_only_manip">quote_only manipulator</a>,
/// except that it uses double quotes instead of single quotes.
///
/// You might care to use it when you have MySQL's \c ANSI_QUOTES mode
/// enabled.  In that mode, single quotes are used only for string
/// literals, and double quotes for identifiers.  Otherwise,
/// \c quote_only and \c quote are quite sufficient.

enum quote_double_only_type0
{
	quote_double_only ///< insert into a std::ostream to double-quote next item
};


#if !defined(DOXYGEN_IGNORE)
// Doxygen will not generate documentation for this section.

struct quote_double_only_type1
{
	std::ostream* ostr;
	quote_double_only_type1(std::ostream* o) :
	ostr(o)
	{
	}
};


inline quote_double_only_type1
operator <<(std::ostream& o, quote_double_only_type0 /* esc */)
{
	return quote_double_only_type1(&o);
}


struct quote_double_only_type2
{
	SQLQueryParms *qparms;
	quote_double_only_type2(SQLQueryParms* p) :
	qparms(p)
	{
	}
};


inline quote_double_only_type2
operator <<(SQLQueryParms& p, quote_double_only_type0 /* esc */)
{
	return quote_double_only_type2(&p);
}


/// \brief Inserts a SQLTypeAdapter into a stream, double-quoting it (")
/// unless it's data that needs no quoting.
///
/// We make the decision to quote the data based on the in.quote_q()
/// flag.  You can set it yourself, but SQLTypeAdapter's ctors should set
/// it correctly for you.

MYSQLPP_EXPORT SQLQueryParms&
operator <<(quote_double_only_type2 p, SQLTypeAdapter& in);


MYSQLPP_EXPORT std::ostream&
operator <<(quote_double_only_type1 o, const SQLTypeAdapter& in);


template <class ST>
inline std::ostream&
operator <<(quote_double_only_type1 o, const Set<ST>& in)
{
	return *o.ostr << '"' << in << '"';
}

#endif // !defined(DOXYGEN_IGNORE)


/// \enum escape_type0
/// The 'escape' manipulator.
///
/// SQL-escapes following argument if it is of a data type that
/// may require escaping when inserted into a Query or SQLQueryParms
/// stream.  This is useful with string types, for example, to avoid
/// bad SQL when they contain special characters like single quotes,
/// nulls, and newlines.  Data types like integers which never benefit
/// from escaping don't get run through the escaping routine even if
/// you ask for it.

enum escape_type0 { escape };


#if !defined(DOXYGEN_IGNORE)
// Doxygen will not generate documentation for this section.

struct escape_type1
{
	std::ostream* ostr;
	escape_type1(std::ostream* o) :
	ostr(o)
	{
	}
};


inline escape_type1
operator <<(std::ostream& o, escape_type0 /* esc */)
{
	return escape_type1(&o);
}


struct escape_type2
{
	SQLQueryParms *qparms;
	escape_type2(SQLQueryParms* p) :
	qparms(p)
	{
	}
};


inline escape_type2
operator <<(SQLQueryParms& p, escape_type0 /* esc */)
{
	return escape_type2(&p);
}

#endif // !defined(DOXYGEN_IGNORE)


/// \brief Inserts a SQLTypeAdapter into a stream, escaping special SQL
/// characters
///
/// We actually only do the escaping if in.escape_q() returns true but
/// in.dont_escape is not.  If that is not the case, we insert the
/// string data directly.

MYSQLPP_EXPORT SQLQueryParms&
operator <<(escape_type2 p, SQLTypeAdapter& in);


/// \brief Inserts anything that can be converted to SQLTypeAdapter into
/// a stream, escaping special SQL characters as needed.

MYSQLPP_EXPORT std::ostream&
operator <<(escape_type1 o, const SQLTypeAdapter& in);


/// \enum do_nothing_type0
/// \anchor do_nothing_manip
///
/// The 'do_nothing' manipulator.
///
/// Does exactly what it says: nothing. Used as a dummy manipulator when
/// you are required to use some manipulator but don't want anything to
/// be done to the following item. When used with SQLQueryParms it will
/// make sure that it does not get formatted in any way, overriding any
/// setting set by the template query.

enum do_nothing_type0
{
	do_nothing				///< insert into a std::ostream to override manipulation of next item
};


#if !defined(DOXYGEN_IGNORE)
// Doxygen will not generate documentation for this section.

struct do_nothing_type1
{
	std::ostream* ostr;
	do_nothing_type1(std::ostream* o) :
	ostr(o)
	{
	}
};


inline do_nothing_type1
operator <<(std::ostream& o, do_nothing_type0 /* esc */)
{
	return do_nothing_type1(&o);
}


MYSQLPP_EXPORT std::ostream&
operator <<(do_nothing_type1 o, const SQLTypeAdapter& in);


struct do_nothing_type2
{
	SQLQueryParms *qparms;
	do_nothing_type2(SQLQueryParms* p) :
	qparms(p)
	{
	}
};


inline do_nothing_type2
operator <<(SQLQueryParms& p, do_nothing_type0 /* esc */)
{
	return do_nothing_type2(&p);
}


/// \brief Inserts a SQLTypeAdapter into a stream, with no escaping or
/// quoting.

MYSQLPP_EXPORT SQLQueryParms&
operator <<(do_nothing_type2 p, SQLTypeAdapter& in);

#endif // !defined(DOXYGEN_IGNORE)


/// \enum ignore_type0
/// \anchor ignore_manip
///
/// The 'ignore' manipulator.
///
/// Only valid when used with SQLQueryParms. It's a dummy manipulator
/// like the <a href="#do_nothing_manip">do_nothing manipulator</a>,
/// except that it will not override formatting set by the template
/// query.  It is simply ignored.

enum ignore_type0
{
	ignore					///< insert into a std::ostream as a dummy manipulator
};


#if !defined(DOXYGEN_IGNORE)
// Doxygen will not generate documentation for this section.

struct ignore_type2
{
	SQLQueryParms* qparms;
	ignore_type2(SQLQueryParms* p) :
	qparms(p)
	{
	}
};


inline ignore_type2
operator <<(SQLQueryParms& p, ignore_type0 /* esc */)
{
	return ignore_type2(&p);
}


/// \brief Inserts a SQLTypeAdapter into a stream, with no escaping or
/// quoting, and without marking the string as having been "processed".

MYSQLPP_EXPORT SQLQueryParms&
operator <<(ignore_type2 p, SQLTypeAdapter& in);

#endif // !defined(DOXYGEN_IGNORE)

} // end namespace mysqlpp

#endif
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
|
<
<
<
<
<
|
<
|
<
<
<
<
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
|
|
<
<
|
<
|
<
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<

|
<
<
<
<
<
<
|
<
<
|
|
<
<
<
<
<
<
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
|
<
<
|
|
<
<
<
<
<
|
|
<
<
<
<
<
<

<
<
|
|
<
<
|
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<

<
<
<
<
<
<
<
<
|
|
<
<
<
<
<
|
|
<
<
<
<
<
<
<
<
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<

<
|
|
<
<
|
<
<
<
<
<
<
<
<
|
|
<
<
<
<
<
|

<
<
<
<
<
<
<
<
|
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<

<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
|
<
<
|
|
<
<
|
<
<
|
<
|
|
<
<
<
<
<
<
<
<
<
|
<
<
<
<
|
|
<
<
|
<
<
<
<
<
<
<
<
|
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<















1





2

3




4














5
6


7

8

9








































































10
11






12


13
14






15










































16


17
18





19
20






21


22
23


24
25































26








27
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

































<?xml version="1.0" encoding="UTF-8"?>





<!DOCTYPE article PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"

                         "http://www.docbook.org/xml/4.2/docbookx.dtd"




[ <!ENTITY % xinclude SYSTEM "xinclude.mod">














%xinclude;
]>


<article>

	<articleinfo>

		<title>MySQL++ v3.1.0 User Manual</title>









































































		<authorgroup>






			<author>


				<firstname>Kevin</firstname>
				<surname>Atkinson</surname>






			</author>













































			<author>
				<firstname>Sinisa</firstname>





				<surname>Milivojevic</surname>
			</author>









			<author>
				<firstname>Monty</firstname>


				<surname>Widenius</surname>
			</author>








































			<author>
				<firstname>Warren</firstname>





				<surname>Young</surname>
			</author>








		</authorgroup>













































		<copyright>
			<year>1998-2001, 2005-2010</year>


			<holder>Kevin Atkinson (original author)</holder>








			<holder>MySQL AB</holder>
			<holder>Educational Technology Resources</holder>





		</copyright>









		<pubdate><?dbtimestamp format="B d, Y"?></pubdate>
	</articleinfo>



















































































	<xi:include href="intro.dbx" xmlns:xi="http://www.w3.org/2001/XInclude"/>
	<xi:include href="overview.dbx" xmlns:xi="http://www.w3.org/2001/XInclude"/>


	<xi:include href="tutorial.dbx" xmlns:xi="http://www.w3.org/2001/XInclude"/>


	<xi:include href="tquery.dbx" xmlns:xi="http://www.w3.org/2001/XInclude"/>

	<xi:include href="ssqls.dbx" xmlns:xi="http://www.w3.org/2001/XInclude"/>
	<xi:include href="unicode.dbx" xmlns:xi="http://www.w3.org/2001/XInclude"/>









	<xi:include href="threads.dbx" xmlns:xi="http://www.w3.org/2001/XInclude"/>




	<xi:include href="configuration.dbx" xmlns:xi="http://www.w3.org/2001/XInclude"/>
	<xi:include href="incorporating.dbx" xmlns:xi="http://www.w3.org/2001/XInclude"/>


	<xi:include href="breakages.dbx" xmlns:xi="http://www.w3.org/2001/XInclude"/>








	<xi:include href="licenses.dbx" xmlns:xi="http://www.w3.org/2001/XInclude"/>
</article>


















Changes to lib/myset.cpp.


1



2
3
4

5





6


7



8



9






10






11
12
13







14
15



16




17














18



19




20

21
22
23
24
25
26

27
28

29
30


31
32


33
34


35

/***********************************************************************



 myset.cpp - Implements the Set template.  (Not to be confused with
	std::set, which this template wraps.)


 Copyright (c) 1998 by Kevin Atkinson, (c) 1999, 2000 and 2001 by





 MySQL AB, and (c) 2004, 2005 by Educational Technology Resources, Inc.


 Others may also hold copyrights on code in this file.  See the CREDITS



 file in the top directory of the distribution for details.










 This file is part of MySQL++.







 MySQL++ is free software; you can redistribute it and/or modify it
 under the terms of the GNU Lesser General Public License as published







 by the Free Software Foundation; either version 2.1 of the License, or
 (at your option) any later version.








 MySQL++ is distributed in the hope that it will be useful, but WITHOUT














 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or



 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public




 License for more details.


 You should have received a copy of the GNU Lesser General Public
 License along with MySQL++; if not, write to the Free Software
 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
 USA
***********************************************************************/


#include "myset.h"


namespace mysqlpp {



template class Set<std::set<std::string> >;



} // end namespace mysqlpp



>
|
>
>
>
|
|

>
|
>
>
>
>
>
|
>
>
|
>
>
>
|
>
>
>

>
>
>
>
>
>
|
>
>
>
>
>
>

|
|
>
>
>
>
>
>
>
|
|
>
>
>
|
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
>
>
|
>
>
>
>
|
>
|
<
|
<
<
<
>
|
|
>
|
|
>
>
|
|
>
>
|
|
>
>

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
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
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87

88



89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
#include "util.h"

#include <iostream>
#include <iomanip>
#include <stdlib.h>

using namespace std;

const char* kpcSampleDatabase = "mysql_cpp_data";

void
print_stock_table(mysqlpp::Query& query)
{
	// You must reset the query object when re-using it.
	query.reset();

	// You can write to the query object like you would any ostream.
	query << "select * from stock";

	// Show the query string.  If you do this, you have to do it before
	// you execute() or store() or use() it.
	cout << "Query: " << query.preview() << endl;

	// Execute the query and save the results.
	mysqlpp::Result res = query.store();
	cout << "Records Found: " << res.size() << endl << endl;

	// Display a header for the stock table
	cout.setf(ios::left);
	cout << setw(20) << "Item" <<
			setw(9) << "Num" <<
			setw(9) << "Weight" <<
			setw(9) << "Price" << "Date" << endl << endl;

	// Use the Result class's read-only random access iterator to walk
	// through the query results.
	mysqlpp::Row row;
	mysqlpp::Result::iterator i;
	for (i = res.begin(); i != res.end(); ++i) {
		row = *i;

		// Note that you can use either the column index or name to
		// retrieve the data.
		cout << setw(20) << row[0].c_str() <<
				setw(9) << row[1].c_str() <<
				setw(9) << row.lookup_by_name("weight").c_str() <<
				setw(9) << row[3].c_str() <<
				row[4] << endl;
	}
}


bool
connect_to_db(int argc, char *argv[], mysqlpp::Connection& con,
		const char *kdb)
{
	if (argc < 1) {
		cerr << "Bad argument count: " << argc << '!' << endl;
		return false;
	}

	if ((argc > 1) && (argv[1][0] == '-')) {
		cout << "usage: " << argv[0] <<
				" [host] [user] [password] [port]" << endl;
		cout << endl << "\tConnects to database ";
		if (kdb) {
			cout << '"' << kdb << '"';
		}
		else {
			cout << "server";
		}
		cout << " on localhost using your user" << endl;
		cout << "\tname and no password by default." << endl << endl;
		return false;
	}

	if (!kdb) {
		kdb = kpcSampleDatabase;
	}

	bool success = false;
	if (argc == 1) {
		success = con.connect(kdb);
	}
	else if (argc == 2) {
		success = con.connect(kdb, argv[1]);
	}

	else if (argc == 3) {



		success = con.connect(kdb, argv[1], argv[2]);
	}
	else if (argc == 4) {
		success = con.connect(kdb, argv[1], argv[2], argv[3]);
	}
	else if (argc >= 5) {
		success = con.real_connect(kdb, argv[1], argv[2], argv[3],
				atoi(argv[4]));
	}

	if (!success) {
		cerr << "Database connection failed." << endl << endl;
	}

	return success;
}

Changes to lib/myset.h.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
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
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
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
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
/// \file myset.h
/// \brief Declares templates for generating custom containers used
/// elsewhere in the library.

/***********************************************************************
 Copyright (c) 1998 by Kevin Atkinson, (c) 1999-2001 by MySQL AB, and
 (c) 2004-2007 by Educational Technology Resources, Inc.  Others may
 also hold copyrights on code in this file.  See the CREDITS.txt file
 in the top directory of the distribution for details.

 This file is part of MySQL++.

 MySQL++ is free software; you can redistribute it and/or modify it
 under the terms of the GNU Lesser General Public License as published
 by the Free Software Foundation; either version 2.1 of the License, or
 (at your option) any later version.

 MySQL++ is distributed in the hope that it will be useful, but WITHOUT
 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
 License for more details.

 You should have received a copy of the GNU Lesser General Public
 License along with MySQL++; if not, write to the Free Software
 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
 USA
***********************************************************************/

#ifndef MYSQLPP_MYSET_H
#define MYSQLPP_MYSET_H

#include "common.h"

#include "mystring.h"
#include "stream2string.h"

#include <iostream>
#include <set>

namespace mysqlpp {

#if !defined(DOXYGEN_IGNORE)
// Doxygen will not generate documentation for this section.

template <class T, class key_type = typename T::key_type>
class MYSQLPP_EXPORT SetInsert
{
public:
	SetInsert(T* o) : object_(o) { }
	void operator ()(const key_type& data) { object_->insert(data); }

private:
	T* object_;
};

template <class T>
inline SetInsert< std::set<T> > set_insert(std::set<T>* o)
{
	return SetInsert< std::set<T> >(o);
}

template <class Insert>
void set2container(const char* str, Insert insert);

#endif // !defined(DOXYGEN_IGNORE)


/// \brief A special std::set derivative for holding MySQL data sets.

template <class Container = std::set<std::string> >
class MYSQLPP_EXPORT Set : public Container
{
public:
	/// \brief Default constructor
	Set() {};

	/// \brief Create object from a comma-separated list of values
	Set(const char* str)
	{
		set2container(str, set_insert(this));
	}
	
	/// \brief Create object from a comma-separated list of values
	Set(const std::string& str)
	{
		set2container(str.c_str(), set_insert(this));
	}
	
	/// \brief Create object from a comma-separated list of values
	Set(const String& str)
	{
		set2container(str.c_str(), set_insert(this));
	}

	/// \brief Convert this set's data to a string containing
	/// comma-separated items.
	operator std::string() const { return stream2string(*this); }

	/// \brief Return our value in std::string form
	std::string str() const { return *this; }
};


/// \brief Inserts a Set object into a C++ stream
template <class Container>
inline std::ostream& operator <<(std::ostream& s,
		const Set<Container>& d)
{
	typename Container::const_iterator i = d.begin();
	typename Container::const_iterator e = d.end();

	if (i != e) {
		while (true) {
			s << *i;
			if (++i == e) {
				break;
			}
			s << ",";
		}
	}
	
	return s;
}


#if !defined(DOXYGEN_IGNORE)
// Doxygen will not generate documentation for this section.

template <class Insert>
void set2container(const char* str, Insert insert)
{
	std::string temp;

	// Break str up using comma separators
	while (str && *str) {
		if (*str == ',') {
			insert(temp);
			temp.clear();

			// Handle comma at end of string case
			if (*++str) {
				++str;
			}
		}
		else {
			temp += *str++;
		}
	}

	// Save final element of set, if any
	if (temp.size()) {
		insert(temp);
	}
}

#endif // !defined(DOXYGEN_IGNORE)


} // end namespace mysqlpp

#endif
|
|
|

<


|
|



















|
|

<
<
<
<
<
<
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<

<
<
<
|
|
<
<
<
<
<
<
<
|
<
<
<
<
<
<
<
<
<
|
<
<
|
|
<
<
|
<
<
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
|

<
<
<
<
1
2
3
4

5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30






31



























































32



33
34







35









36


37
38


39


40
























41
42




/***********************************************************************
 printdata.h - Declares utility routines for printing out data in
    common forms, used by most of the example programs.


 Copyright (c) 1998 by Kevin Atkinson, (c) 1999-2001 by MySQL AB, and
 (c) 2004-2007 by Educational Technology Resources, Inc.  Others may
 also hold copyrights on code in this file.  See the CREDITS file in
 the top directory of the distribution for details.

 This file is part of MySQL++.

 MySQL++ is free software; you can redistribute it and/or modify it
 under the terms of the GNU Lesser General Public License as published
 by the Free Software Foundation; either version 2.1 of the License, or
 (at your option) any later version.

 MySQL++ is distributed in the hope that it will be useful, but WITHOUT
 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
 License for more details.

 You should have received a copy of the GNU Lesser General Public
 License along with MySQL++; if not, write to the Free Software
 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
 USA
***********************************************************************/

#if !defined(MYSQLPP_PRINTDATA_H)
#define MYSQLPP_PRINTDATA_H







#include <mysql++.h>































































void print_stock_header(int rows);
void print_stock_row(const mysqlpp::Row& r);







void print_stock_row(const mysqlpp::sql_char& item,









		mysqlpp::sql_bigint num, mysqlpp::sql_double weight,


		mysqlpp::sql_decimal price, const mysqlpp::sql_date& date);
void print_stock_rows(mysqlpp::StoreQueryResult& res);


void print_stock_table(mysqlpp::Query& query);



























#endif // !defined(MYSQLPP_PRINTDATA_H)





Changes to lib/mysql++.cpp.

1
2
3


4

5
6
7
8
9
10
11
12
/***********************************************************************
 mysql++.cpp - Implements functions dealing with the library itself,
	as opposed to individual features of the library.




 Copyright (c) 2007 by Educational Technology Resources, Inc.
 Others may also hold copyrights on code in this file.  See the CREDITS
 file in the top directory of the distribution for details.

 This file is part of MySQL++.

 MySQL++ is free software; you can redistribute it and/or modify it
 under the terms of the GNU Lesser General Public License as published

|
|
>
>

>
|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/***********************************************************************
 resetdb.cpp - (Re)initializes the example database, mysql_cpp_data.
 	You must run this at least once before running most of the other
	examples, and it is helpful sometimes to run it again, as some of
	the examples modify the table in this database.

 Copyright (c) 1998 by Kevin Atkinson, (c) 1999, 2000 and 2001 by
 MySQL AB, and (c) 2004, 2005 by Educational Technology Resources, Inc.
 Others may also hold copyrights on code in this file.  See the CREDITS
 file in the top directory of the distribution for details.

 This file is part of MySQL++.

 MySQL++ is free software; you can redistribute it and/or modify it
 under the terms of the GNU Lesser General Public License as published
20
21
22
23
24
25
26
27
28




29
30

31

32
33





34
35
36
37


38






























































































































 You should have received a copy of the GNU Lesser General Public
 License along with MySQL++; if not, write to the Free Software
 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
 USA
***********************************************************************/

#include "mysql++.h"





namespace mysqlpp {


unsigned int

get_library_version()
{





	return MYSQLPP_HEADER_VERSION;
}

} // end namespace mysqlpp







































































































































|

>
>
>
>
|

>
|
>
|

>
>
>
>
>
|


|
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
23
24
25
26
27
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
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
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
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

 You should have received a copy of the GNU Lesser General Public
 License along with MySQL++; if not, write to the Free Software
 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
 USA
***********************************************************************/

#include "util.h"

#include <mysql++.h>

#include <iostream>

using namespace std;

// Convert a packed version number in the format used within MySQL++
// to a printable string.
static string
version_str(int packed)
{
	char buf[9];
	snprintf(buf, sizeof(buf), "%d.%d.%d",
			(packed & 0xFF0000) >> 16,
			(packed & 0x00FF00) >> 8,
			(packed & 0x0000FF));
	return buf;
}


int
main(int argc, char *argv[])
{
	// Ensure that we're not mixing library and header file versions.
	// This is really easy to do if you have MySQL++ on your system and
	// are trying to build a new version, and run the examples directly
	// instead of through exrun.
	if (mysqlpp::get_library_version() != MYSQLPP_HEADER_VERSION) {
		cerr << "Version mismatch: library is v" <<
				version_str(mysqlpp::get_library_version()) <<
				", headers are v" <<
				version_str(MYSQLPP_HEADER_VERSION) <<
				".  Are you running this" << endl <<
				"with exrun?  See README.examples." << endl;
		return 1;
	}
	
	// Connect to database server
	mysqlpp::Connection con;
	try {
		cout << "Connecting to database server..." << endl;
		if (!connect_to_db(argc, argv, con, "")) {
			return 1;
		}
	}
	catch (exception& er) {
		cerr << "Connection failed: " << er.what() << endl;
		return 1;
	}
	
	// Create new sample database, or re-create it.  We suppress
	// exceptions, because it's not an error if DB doesn't yet exist.
	bool new_db = false;
	{
		mysqlpp::NoExceptions ne(con);
		mysqlpp::Query query = con.query();
		if (con.select_db(kpcSampleDatabase)) {
			// Toss old table, if it exists.  If it doesn't, we don't
			// really care, as it'll get created next.
			cout << "Dropping existing sample data tables..." << endl;
			query.execute("drop table stock");
			query.execute("drop table images");
		}
		else {
			// Database doesn't exist yet, so create and select it.
			if (con.create_db(kpcSampleDatabase) &&
					con.select_db(kpcSampleDatabase)) {
				new_db = true;
			}
			else {
				cerr << "Error creating DB: " << con.error() << endl;
				return 1;
			}
		}
	}

	// Create sample data table within sample database.
	try {
		// Send the query to create the stock table and execute it.
		cout << "Creating stock table..." << endl;
		mysqlpp::Query query = con.query();
		query << 
				"CREATE TABLE stock (" <<
				"  item CHAR(20) NOT NULL, " <<
				"  num BIGINT, " <<
				"  weight DOUBLE, " <<
				"  price DOUBLE, " <<
				"  sdate DATE) " <<
				"ENGINE = InnoDB " <<
				"CHARACTER SET utf8 COLLATE utf8_general_ci";
		query.execute();

		// Set up the template query to insert the data.  The parse()
		// call tells the query object that this is a template and
		// not a literal query string.
		query << "insert into %5:table values (%0q, %1q, %2, %3, %4q)";
		query.parse();

		// Set the template query parameter "table" to "stock".
		query.def["table"] = "stock";

		// Notice that we don't give a sixth parameter in these calls,
		// so the default value of "stock" is used.  Also notice that
		// the first row is a UTF-8 encoded Unicode string!  All you
		// have to do to store Unicode data in recent versions of MySQL
		// is use UTF-8 encoding.
		cout << "Populating stock table..." << endl;
		query.execute("Nürnberger Brats", 97, 1.5, 8.79, "2005-03-10");
		query.execute("Pickle Relish", 87, 1.5, 1.75, "1998-09-04");
		query.execute("Hot Mustard", 73, .95, .97, "1998-05-25");
		query.execute("Hotdog Buns", 65, 1.1, 1.1, "1998-04-23");

		// Now create empty images table, for testing BLOB and auto-
		// increment column features.
		cout << "Creating empty images table..." << endl;
		query.reset();
		query << 
				"CREATE TABLE images (" <<
				"  id INT UNSIGNED NOT NULL AUTO_INCREMENT, " <<
				"  data BLOB, " <<
				"  PRIMARY KEY (id)" <<
				")";
		query.execute();

		// Report success
		cout << (new_db ? "Created" : "Reinitialized") <<
				" sample database successfully." << endl;
	}
	catch (const mysqlpp::BadQuery& er) {
		// Handle any query errors
		cerr << "Query error: " << er.what() << endl;
		return 1;
	}
	catch (const mysqlpp::BadConversion& er) {
		// Handle bad conversions
		cerr << "Conversion error: " << er.what() << endl <<
				"\tretrieved data size: " << er.retrieved <<
				", actual size: " << er.actual_size << endl;
		return 1;
	}
	catch (const mysqlpp::Exception& er) {
		// Catch-all for any other MySQL++ exceptions
		cerr << "Error: " << er.what() << endl;
		return 1;
	}

	return 0;
}

Changes to lib/mysql++.h.in.

1
2
3
4
5
6
7
8
9
10
11


12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
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
56
57
58
59
60
61
62
63

64
65
66
67
68
69
70
71
72
73
74

75








76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100


101

102
103
104
105
106
107
108
109
110
111
112
113
114
115
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
144
145
146
147
148
149
150
151
152
153
154
155
156
157
/// \file mysql++.h
/// \brief The main MySQL++ header file.
///
/// This file brings in all MySQL++ headers except for custom.h and
/// custom-macros.h which are a strictly optional feature of MySQL++.
///
/// There is no point in trying to optimize which headers you include,
/// because the MySQL++ headers are so intertwined.  You can only get
/// trivial compile time benefits, at the expense of clarity.

/***********************************************************************


 Copyright (c) 1998 by Kevin Atkinson, (c) 1999-2001 by MySQL AB, and
 (c) 2004-2010 by Educational Technology Resources, Inc.  Others may
 also hold copyrights on code in this file.  See the CREDITS.txt file
 in the top directory of the distribution for details.

 This file is part of MySQL++.

 MySQL++ is free software; you can redistribute it and/or modify it
 under the terms of the GNU Lesser General Public License as published
 by the Free Software Foundation; either version 2.1 of the License, or
 (at your option) any later version.

 MySQL++ is distributed in the hope that it will be useful, but WITHOUT
 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
 License for more details.

 You should have received a copy of the GNU Lesser General Public
 License along with MySQL++; if not, write to the Free Software
 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
 USA
***********************************************************************/

#ifndef MYSQLPP_MYSQLPP_H
#define MYSQLPP_MYSQLPP_H

/// \brief Encode MySQL++ library version number.
///
/// This macro takes major, minor and bugfix numbers (e.g. 1, 2, and 3)
/// and encodes them like 0x010203.
#define MYSQLPP_VERSION(major, minor, bugfix) \
		(((major) << 16) | ((minor) << 8) | (bugfix))

/// \brief Get the library version number that mysql++.h comes from
///
/// MySQL++ Version number that the mysql++.h header file comes from,
/// encoded by MYSQLPP_VERSION macro.  Compare this value to what
/// get_library_version() returns in order to ensure that your program
/// is using header files from the same version of MySQL++ as the
/// actual library you're linking to.
#define MYSQLPP_HEADER_VERSION MYSQLPP_VERSION(@MYSQLPP_VERSION_MAJOR@, @MYSQLPP_VERSION_MINOR@, @MYSQLPP_VERSION_BUGFIX@)

// This #include order gives the fewest redundancies in the #include
// dependency chain.
#include "connection.h"
#include "cpool.h"
#include "query.h"
#include "scopedconnection.h"
#include "sql_types.h"
#include "transaction.h"

namespace mysqlpp {


/// \brief Get the current MySQL++ library version number
///
/// MySQL++ version number that the program is actually linked to,
/// encoded by MYSQLPP_VERSION macro.  Compare this value to the
/// MYSQLPP_HEADER_VERSION constant in order to ensure that your
/// program is using header files from the same version of MySQL++ as
/// the actual library you're linking to.
MYSQLPP_EXPORT unsigned int get_library_version();

// This won't exist forever!  Wean yourself away from these as soon as

// you can!








#if defined(MYSQLPP_OLD_CLASS_NAMES)
#	define ColData String
#	define NullisBlank NullIsBlank
#	define NullisNull NullIsNull
#	define NullisZero NullIsZero
#	define ResNSel SimpleResult
#	define Result StoreQueryResult
#	define ResUse UseQueryResult
#	define SQLString SQLTypeAdapter
#endif

} // end namespace mysqlpp

#endif // !defined(MYSQLPP_MYSQLPP_H)


/**
	\mainpage MySQL++ Reference Manual

	\section getting_started Getting Started

	The best place to get started is the
	<a href="../userman/index.html">user manual</a>. It provides
	a guide to the example programs and more.





	\section classes Major Classes

	In MySQL++, the main user-facing classes are
	mysqlpp::Connection, mysqlpp::Query, mysqlpp::Row,
	mysqlpp::StoreQueryResult, and mysqlpp::UseQueryResult.

	In addition, MySQL++ has a mechanism called Specialized SQL
	Structures (SSQLS), which allow you to create C++ structures
	that parallel the definition of the tables in your database
	schema. These let you manipulate the data in your database using
	native C++ data structures. Programs using this feature often
	include very little SQL code, because MySQL++ can generate most
	of what you need automatically when using SSQLSes. There is a
	whole chapter in the user manual on how to use this feature of
	the library, plus a section in the user manual's tutorial chapter
	to introduce it. It's possible to use MySQL++ effectively without
	using SSQLS, but it sure makes some things a lot easier.


	\section files Major Files

	The only two header files your program ever needs to include
	are mysql++.h, and optionally custom.h. (The latter implements
	the SSQLS mechanism.) All of the other files are used within

	the library only.



	\section user_questions If You Have Questions...

	If you want to email someone to ask questions about this library,
	we greatly prefer that you send mail to the MySQL++ mailing list,
	which you can subscribe to here: http://lists.mysql.com/plusplus

	That mailing list is archived, so if you have questions, do a
	search to see if the question has been asked before.

	You may find people's individual email addresses in various
	files within the MySQL++ distribution. Please do not send mail
	to them unless you are sending something that is inherently
	personal. Questions that are about MySQL++ usage may well be
	ignored if you send them to our personal email accounts. Those of
	us still active in MySQL++ development monitor the mailing list,
	so you aren't getting any extra "coverage" by sending messages
	to those addresses in addition to the mailing list.


	\section licensing Licensing

	MySQL++ is licensed under the GNU Lesser General Public License,
	which you should have received with the distribution package in
	a file called "LGPL" or "LICENSE". You can also view it here:
	http://www.gnu.org/licenses/lgpl.html or receive a copy by
	writing to Free Software Foundation, Inc., 51 Franklin Street,
	Fifth Floor, Boston, MA 02110-1301, USA.
*/

<
<
<
<
<
<
<
<
<
<

>
>
|
|
|
|



















|
|
|
<
<
<
<
<
<
|
<
<
<
<
<
<
<
<

<
<
<
|
<
<
<
<

|
>

<
<
<
<
<
<
<
<

<
>
|
>
>
>
>
>
>
>
>
|
|
|
|
|
|
|
|
|
<
|
|
|
<
|
|
<
<
|
<

<
<
<

>
>
|
>
|
|
|
<
<
|
<
<
<
<
<
<
<
<
<
<
<
|

|
|
<
<
<
>
<

>

|

|
|
<
|
<
<

<
<
<
<
<
<
<
<
|

|
|
<
<
<
<
<
<
<











1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
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
56

57
58
59

60
61


62

63



64
65
66
67
68
69
70
71


72











73
74
75
76



77

78
79
80
81
82
83
84

85


86








87
88
89
90







91










/***********************************************************************
 test/sqlstream.cpp - Tests SQLStream class, which is handled by the 
 stream manipulators just like Query.

 Copyright (c) 2008 by AboveNet, Inc.  Others may also hold copyrights 
 on code in this file.  See the CREDITS file in the top directory of 
 the distribution for details.

 This file is part of MySQL++.

 MySQL++ is free software; you can redistribute it and/or modify it
 under the terms of the GNU Lesser General Public License as published
 by the Free Software Foundation; either version 2.1 of the License, or
 (at your option) any later version.

 MySQL++ is distributed in the hope that it will be useful, but WITHOUT
 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
 License for more details.

 You should have received a copy of the GNU Lesser General Public
 License along with MySQL++; if not, write to the Free Software
 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
 USA
***********************************************************************/

#include <mysql++.h>
#define MYSQLPP_ALLOW_SSQLS_V1	// suppress deprecation warning
#include <ssqls.h>






#include <sqlstream.h>












#include <iostream>





using namespace mysqlpp;
using namespace std;











sql_create_23(test,
	23, 0,
	sql_tinyint,			tinyint_v,
	sql_tinyint_unsigned,	tinyint_unsigned_v,
	sql_smallint,			smallint_v,
	sql_smallint_unsigned,	smallint_unsigned_v,
	sql_int,				int_v,
	sql_int_unsigned,		int_unsigned_v,
	sql_mediumint,			mediumint_v,
	sql_mediumint_unsigned, mediumint_unsigned_v,
	sql_bigint,				bigint_v,
	sql_bigint_unsigned,	bigint_unsigned_v,
	sql_float,				float_v,
	sql_double,				double_v,
	sql_decimal,			decimal_v,
	sql_bool,				bool_v,
	sql_date,				date_v,
	sql_time,				time_v,
	sql_datetime,			datetime_v,

	sql_char,				char_v,
	sql_varchar,			varchar_v,
	sql_tinytext,			tinytext_v,

	sql_text,				text_v,
	sql_mediumtext,			mediumtext_v,


	sql_longtext,			longtext_v)






int
main()
{
	SQLStream sqls(0);		// don't do this in real code
	test empty(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, false,
			Date(), Time(), DateTime(),"","","","","","");
	test filled(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11.0, 12.0, 13.0,


			bool(14), Date("1515-15-15"), Time("16:16:16"),











			DateTime("1717-17-17 17:17:17"),"18","19","20","21","22","23");

	sqls << "INSERT INTO " << filled.table() << " (" <<
			filled.field_list() << ") VALUES (" <<



			filled.value_list() << ")";


	cout << sqls.str() << endl;

	sqls.str("");

	sqls << "INSERT INTO " << empty.table() << " (" <<
			empty.field_list() << ") VALUES (" <<

			empty.value_list() << ")";











	cout << sqls.str() << endl;

	return 0;
}








Changes to lib/mystring.cpp.

1
2



3
4
5
6
7
8
9
10
11
12
13
14


























15
16

17
18
19

20



21

22

23




24
25


26
27
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


56

57







58
59



60


















61

62





63
64

65

66

67

68


69































70
71
72



73






74
75






76


77


78



79





80



81

82
83


























84
85

86
87









88
89
90


91
92

93
94
95
96
97

98

99
100


101


102

103


104





105





106






107



108












109
110




111






112
113
114
115
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
















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
191


192



193






194
195


196
197
198






199











200
201








202


203



204








205
206







207



208
209






210



211


212


213



214







215






216
217
218





219
220



221







222
223
224

225
226
227




228




229




230




231




232




233




234


235

236




237
238



239




240





241
242








243

244


245
246

247

248
249


250



251

252
253
254
255

256
257















/***********************************************************************
 mystring.cpp - Implements the String class.




 Copyright (c) 1998 by Kevin Atkinson, (c) 1999-2001 by MySQL AB, and
 (c) 2004-2008 by Educational Technology Resources, Inc.  Others may
 also hold copyrights on code in this file.  See the CREDITS.txt file
 in the top directory of the distribution for details.

 This file is part of MySQL++.

 MySQL++ is free software; you can redistribute it and/or modify it
 under the terms of the GNU Lesser General Public License as published
 by the Free Software Foundation; either version 2.1 of the License, or
 (at your option) any later version.



























 MySQL++ is distributed in the hope that it will be useful, but WITHOUT

 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
 License for more details.





 You should have received a copy of the GNU Lesser General Public

 License along with MySQL++; if not, write to the Free Software

 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301




 USA
***********************************************************************/



#include "mystring.h"
#include "query.h"




#include <algorithm>
#include <stdexcept>
#include <string>













namespace mysqlpp {








char

String::at(size_type pos) const

{



	if (pos >= size()) {






		throw BadIndex("String", int(pos), int(size()));








	}
	else {

		return buffer_->data()[pos];
	}

}













int



String::compare(const String& other) const

{

	if (other.buffer_) {
		return compare(0, std::max(length(), other.length()),
				other.buffer_->data());
	}


	else {

		// Other object has no buffer, so we are greater unless empty or







		// we also have no buffer.
		return length() > 0 ? 1 : 0;	



	}


















}








int

String::compare(const std::string& other) const

{

	return compare(0, std::max(length(), other.length()), other.data());

}



































int
String::compare(size_type pos, size_type num, std::string& other) const



{






	return compare(pos, num, other.data());
}












int



String::compare(const char* other) const





{



	return compare(0, std::max(length(), strlen(other)), other);

}




























int

String::compare(size_type pos, size_type num,
		const char* other) const









{
	if (buffer_ && other) {
		return strncmp(data() + pos, other, num);


	}
	else if (!other) {

		// Initted and non-empty is "greater than" uninitted
		return length() > 0 ? 1 : 0;
	}
	else {
		// This object has no buffer, so we are less than other object

		// unless it is empty.

		return other[0] == '\0' ? 0 : -1;
	}


}







#if !defined(DOXYGEN_IGNORE)





// Doxygen isn't smart enough to recognize these template





// specializations.  Maybe it's the MYSQLPP_EXPORT tags?










template <>












String
String::conv(String) const { return *this; }












template <>
bool
String::conv(bool) const
{


	return *this;	// delegate to operator bool





}





template <>


std::string
String::conv(std::string) const





{
	return buffer_ ? std::string(data(), length()) : std::string();









}













template <>


Date


String::conv(Date) const
{
	return buffer_ ? Date(c_str()) : Date();







}


template <>

DateTime
String::conv(DateTime) const
{
	return buffer_ ? DateTime(c_str()) : DateTime();










}


















template <>
Time









String::conv(Time) const


{



	return buffer_ ? Time(c_str()) : Time();


}







#endif // !defined(DOXYGEN_IGNORE)








const char*

String::data() const





{






	return buffer_ ? buffer_->data() : 0;



}


String::const_iterator


String::end() const







{





	return buffer_ ? buffer_->data() + buffer_->length() : 0;


}













bool


String::escape_q() const









{
	return buffer_ ? buffer_->type().escape_q() : false;

}














bool


String::is_null() const

{








	return buffer_ ? buffer_->is_null() : false;



}





void
String::it_is_null()





{


	if (buffer_) {
		buffer_->set_null();
	}


	else {
		buffer_ = new SQLBuffer(0, 0, mysql_type_info::string_type, true);
	}


}











String::size_type


String::length() const
{
	return buffer_ ? buffer_->length() : 0;






}





















bool


String::quote_q() const



{








	// If no buffer, it means we're an empty string, so we need to be 
	// quoted to be expressed properly in SQL.







	return buffer_ ? buffer_->type().quote_q() : true;



}











void


String::to_string(std::string& s) const


{



	if (buffer_) {







		s.assign(buffer_->data(), buffer_->length());






	}
	else {
		s.clear();





	}
}












/// \brief Stream insertion operator for String objects
///

/// This doesn't have anything to do with the automatic quoting and
/// escaping you get when using SQLTypeAdapter with Query.  The need to
/// use String with Query should be rare, since String generally comes




/// in result sets; it should only go back out as queries when using




/// result data in a new query.  Since SQLTypeAdapter has a conversion




/// ctor for String, this shouldn't be a problem.  It's just trading




/// simplicity for a tiny bit of inefficiency in a rare case.  And 




/// since String and SQLTypeAdapter can share a buffer, it's not all




/// that inefficient anyway.







std::ostream&

operator <<(std::ostream& o, const String& in)




{
	if (dynamic_cast<Query*>(&o)) {



		// We can just insert the raw data into the stream




		o.write(in.data(), in.length());





	}
	else {








		// Can't guess what sort of stream it is, so convert the String

		// to a std::string so we can use the formatted output method.


		// To see why this is necessary, change it to use write() only
		// (unformatted output) and then run simple2: notice that the

		// columnar output formatting is wrecked.

		std::string temp;
		in.to_string(temp);


		o << temp;



	}

	return o;
}




} // end namespace mysqlpp















|
|
>
>
>
|
|
|
|
|
|
|
|
|
|
|
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

|
>
|
<
|
>

>
>
>
|
>
|
>
|
>
>
>
>
|
<
>
>

|
|

>
>
>
|
<

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



>

>
>
>
>
>
|
>
|
>
|
>
>
>
|
>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
|
|
>
|
|
>


>
>
>
>
>
>
>
>
>
>
>
|
|
>
>
>
|
>

>
|
|
<
|
>
>
|
>
|
>
>
>
>
>
>
>
|
|
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>

>
>
>
>
>
|
|
>
|
>
|
>
|
>
|
>
>

>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
|
|
>
>
>
|
>
>
>
>
>
>
|
|
>
>
>
>
>
>

>
>

>
>
|
>
>
>
|
>
>
>
>
>
|
>
>
>
|
>


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

<
>
|
<
>
>
>
>
>
>
>
>
>
|
<
<
>
>
|
<
>
|
<
|
<
<
>
|
>
|
|
>
>
|
>
>

>

>
>
|
>
>
>
>
>
|
>
>
>
>
>
|
>
>
>
>
>
>

>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
|
<
>
>
>
>
|
>
>
>
>
>
>
|
<
<
<
|
>
>
|
>
>
>
>
>
|
|
>
>
>

|
>
>
|
|
>
>
>
>
>
|
<
>
>
>
>
>
>
>
>
>
|

>
>
>
>
>
>
>
>
>
>
>

|
>
>
|
>
>
|
<
<
>
>
>
>
>
>
>
|

<
|
>
|
|
<
<
>
>
>
>
>
>
>
>
>
>
|

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

|
|
>
>
>
>
>
>
>
>
>
|
>
>
|
>
>
>
|
>
>
|
>
>
>
>
>
>

<
>
>
>
>
>

>

|
>
|
>
>
>
>
>
|
>
>
>
>
>
>
|
>
>
>
|
|
|
|
>
>
|
>
>
>
>
>
>
>
|
>
>
>
>
>
|
>
>
|
|
>
>
>
>
>
>
>
>
>
>
>

<
>
>
|
>
>
>
>
>
>
>
>
>
|
<
>
|
|
>
>
>
>
>
>
>

>
>
>
>
>
|
>
>
|
>
|
>
>
>
>
>
>
>
>
|
>
>
>
|
|
>
>
>
|
|
|
>
>
>
>
>
|
>
>
|
<
|
>
>
|
<
|
>
>
|
>
>
>
|
>
>
>
>
>
>
|
|
>
>
|
|
<
>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
|

>
>
>
>
>
>
>
>
|
>
>
|
>
>
>
|
>
>
>
>
>
>
>
>
|
<
>
>
>
>
>
>
>
|
>
>
>
|

>
>
>
>
>
>

>
>
>
|
>
>
|
>
>
|
>
>
>
|
>
>
>
>
>
>
>
|
>
>
>
>
>
>

|
|
>
>
>
>
>

|
>
>
>

>
>
>
>
>
>
>

|
<
>
|
|
|
>
>
>
>
|
>
>
>
>
|
>
>
>
>
|
>
>
>
>
|
>
>
>
>
|
>
>
>
>
|
>
>
>
>

>
>
|
>
|
>
>
>
>
|
|
>
>
>
|
>
>
>
>
|
>
>
>
>
>

|
>
>
>
>
>
>
>
>
|
>
|
>
>
|
<
>
|
>
|
|
>
>
|
>
>
>
|
>
|



>


>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
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
56
57
58
59
60
61
62
63

64
65
66
67
68
69
70
71
72
73

74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
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
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
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
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
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
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
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
372
373
374
375
376
377
378
379
380
381

382
383
384
385
386
387
388
389
390
391
392
393



394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419

420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449


450
451
452
453
454
455
456
457
458

459
460
461
462


463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520

521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584

585
586
587
588
589
590
591
592
593
594
595
596
597

598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648

649
650
651
652

653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672

673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717

718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788

789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868

869
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
#!/usr/bin/perl -w

########################################################################
# ssqls.pl - Generates ssqls.h, as it defines many near-duplicate
#	functions and classes, varying only in trivial ways.
#
# Copyright (c) 1998 by Kevin Atkinson, (c) 1999-2001 by MySQL AB, and
# (c) 2004-2010 by Educational Technology Resources, Inc.  Others may
# also hold copyrights on code in this file.  See the CREDITS.txt file
# in the top directory of the distribution for details.
#
# This file is part of MySQL++.
#
# MySQL++ is free software; you can redistribute it and/or modify it
# under the terms of the GNU Lesser General Public License as published
# by the Free Software Foundation; either version 2.1 of the License, or
# (at your option) any later version.
#
# MySQL++ is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
# License for more details.
#
# You should have received a copy of the GNU Lesser General Public
# License along with MySQL++; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
# USA
########################################################################


# This is the limit on the number of SSQLS data members.  Higher values
# will make ssqls.h exponentially larger.  This will increase compile
# times and may even expose limits in your compiler.  Increase it only
# if and as far as you must.
my $max_data_members = 25;

# To make comparisons between floating point values, we subtract them,
# take the absolute value, and test to see if that delta is under this
# value.  If it is, we call the two values "equal".  Change this as fits
# your need for precision.  Note that we express it as a string because
# we want the value copied literally into ssqls.h, not "preprocessed" 
# by Perl as a floating-point value.
my $fp_min_delta = "0.00001";


# No user-serviceable parts below.


use strict;
use Getopt::Std;

our $opt_f;
getopts('f:') or die "usage: $0 [-f fields]\n\n";
$max_data_members = int($opt_f) if defined $opt_f;

open (OUT, ">ssqls.h");

print OUT << "---";

// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
// This file is generated by the Perl script ssqls.pl.  Do not modify
// it directly.  Change the script instead.
// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!


#if !defined(MYSQLPP_SSQLS_H)
#define MYSQLPP_SSQLS_H

#include "noexceptions.h"
#include "sql_types.h"

#if !defined(MYSQLPP_SSQLS_COMPATIBLE)
#	error Your compiler is not compatible with the SSQLS feature!
#endif


#include <string>

#include <math.h>

// Smallest difference between two floating point numbers recognized
// in making comparisons.  If the absolute delta is under this
// threshold, the two values are considered equal.  You can either
// override this permanently by changing ssqls.pl, or you can do it
// on a case-by-case basis at compile time by defining this to another
// value before #including this header.
#if !defined(MYSQLPP_FP_MIN_DELTA)
#	define MYSQLPP_FP_MIN_DELTA $fp_min_delta
#endif

namespace mysqlpp {

enum sql_dummy_type { sql_dummy };

#ifdef MYSQLPP_SSQLS_NO_STATICS
#	define MYSQLPP_SSQLS_CONDITIONAL_STATICS(...)
#else
#	define MYSQLPP_SSQLS_CONDITIONAL_STATICS(...) __VA_ARGS__
#endif

#define MYSQLPP_SSQLS_MAX_MEMBERS $max_data_members

---

my @types = ("Date", "DateTime", "Time", "String", "std::string");
foreach my $type (@types) {
	print OUT << "---";

inline int sql_cmp(const $type& a, const $type& b)
{
	return a.compare(b);
}
---
}

@types = (
		"signed char", "unsigned char",
		"sql_tinyint", "sql_tinyint_unsigned",
		"signed int", "unsigned",
		"signed short", "unsigned short",
		"signed long", "unsigned long");
foreach my $type (@types) {
	print OUT << "---";

inline int sql_cmp($type a, $type b)
{
	return a - b;
}
---
}

@types = ("longlong", "ulonglong");
foreach my $type (@types) {
	print OUT << "---";

inline int sql_cmp($type a, $type b) 
{
	if (a == b) return 0;
	if (a <  b) return -1;
	return 1;
}
---
}	

@types = ("double", "float");
foreach my $type (@types) {
	print OUT << "---";

inline int sql_cmp($type a, $type b) 
{
	if (fabs(a - b) < MYSQLPP_FP_MIN_DELTA) return 0;
	if (a <  b) return -1;
	return 1;

}
---
}	

print OUT << "---";

template <typename T>
inline int sql_cmp(const mysqlpp::Null<T>& a, const mysqlpp::Null<T>& b) 
{
	if (a == b) return 0;
	if (a <  b) return -1;
	return 1;
}


// ---------------------------------------------------
//                Begin Mandatory Compare 
// ---------------------------------------------------

#define sql_compare_define(NAME) \\
	bool operator == (const NAME &other) const \\
		{return sql_compare_##NAME<mysqlpp::sql_dummy>(*this,other) == 0;} \\
	bool operator != (const NAME &other) const \\
		{return sql_compare_##NAME<mysqlpp::sql_dummy>(*this,other) != 0;} \\
	bool operator > (const NAME &other) const \\
		{return sql_compare_##NAME<mysqlpp::sql_dummy>(*this,other) >  0;} \\
	bool operator < (const NAME &other) const \\
		{return sql_compare_##NAME<mysqlpp::sql_dummy>(*this,other) <  0;} \\
	bool operator >= (const NAME &other) const \\
		{return sql_compare_##NAME<mysqlpp::sql_dummy>(*this,other) >= 0;} \\
	bool operator <= (const NAME &other) const \\
		{return sql_compare_##NAME<mysqlpp::sql_dummy>(*this,other) <= 0;} \\
	int cmp (const NAME &other) const \\
		{return sql_compare_##NAME<mysqlpp::sql_dummy>(*this,other);} \\
	int compare (const NAME &other) const \\
		{return sql_compare_##NAME<mysqlpp::sql_dummy>(*this,other);}
---

my ($parm0, $parm1);

foreach my $j (1..$max_data_members) {
	$parm0 .= "T$j, C$j";
	$parm0 .= ", " unless $j == $max_data_members;
	$parm1 .= "C$j";
	$parm1 .= ", " unless $j == $max_data_members;
}

print OUT << "---";

#define sql_compare_define_0(NAME, $parm0)

#define sql_construct_define_0(NAME, $parm0)

#define sql_COMPARE__0(NAME, $parm1)

#define sql_compare_type_def_0(NAME, WHAT, NUM) \\
	sql_compare_type_def_##NUM(NAME, WHAT, NUM)

#define sql_compare_type_defe_0(NAME, WHAT, NUM) \\
	sql_compare_type_defe_##NUM(NAME, WHAT, NUM)

// ---------------------------------------------------
//                 End Mandatory Compare 
// ---------------------------------------------------
---


foreach my $i (1..$max_data_members) {
	my ($compr, $define, $compp, $set, $parm2);

	$compr = ""; $parm2 = ""; $define = "";
	$compr = "    int cmp; \\\n" unless $i == 1;
	$compp = "";
	$set = "";

	foreach my $j (1..$i) {
		if ($j != $i) {
			$compr .= "    cmp = mysqlpp::sql_cmp(x.C$j , y.C$j ); \\\n";
			$compr .= "    if (cmp) return cmp; \\\n";
		}

		$compr .= "    return mysqlpp::sql_cmp(x.C$j , y.C$j );" if $j == $i;
		$parm2 .= "const T$j &p$j";
		$parm2 .= ", " unless $j == $i;
		$define.= "C$j (p$j)";
		$define.= ", " unless $j == $i;
		$set   .= "    C$j = p$j;\\\n";
		$compp .= "true";
		$compp .= ", " unless $j == $i;
	}
	print OUT << "---";

// ---------------------------------------------------
//                   Begin Compare $i
// ---------------------------------------------------

#define sql_compare_define_$i(NAME, $parm0) \\
	NAME($parm2) : $define, table_override_(0) {} \\
	void set($parm2) { \\
	table_override_ = 0; \\
$set \\
	} \\
	sql_compare_define(NAME)

#define sql_construct_define_$i(NAME, $parm0) \\
	void set($parm2) { \\
	table_override_ = 0; \\
$set \\
	} \\
	NAME($parm2) : $define, table_override_(0) {}

#define sql_compare_type_def_$i(NAME, WHAT, NUM) \\
	return WHAT##_list(d, m, $compp)

#define sql_compare_type_defe_$i(NAME, WHAT, NUM) \\
	return WHAT##_list(d, c, m, $compp)

#define sql_COMPARE__$i(NAME, $parm1) \\
	template <mysqlpp::sql_dummy_type dummy> \\
	int sql_compare_##NAME(const NAME &x, const NAME &y) { \\
$compr \\
	} \\
	template <mysqlpp::sql_dummy_type dummy> \\
	int compare (const NAME &x, const NAME &y) { \\
$compr \\
	}

// ---------------------------------------------------
//                   End Compare $i
// ---------------------------------------------------

---
}


foreach my $i (1..$max_data_members) {
	my $create_bool = "";
	my $create_list = "";
	my $cus_equal_list = "";
	my $cus_field_list = "";
	my $cusparms1 = "";
	my $cusparms11 = "";
	my $cusparms2 = "";
	my $cusparms22 = "";
	my $cusparmsv = "";
	my $defs = "";
	my $enums = "";
	my $equal_list = "";
	my $field_list = "";
	my $names = "";
	my $parmc = "";
	my $parmC = "";
	my $parm_complete = "";
	my $parm_simple = "";
	my $parm_simple2c = "";
	my $parm_simple2c_b = "";
	my $parm_simple_b = "";
	my $popul = "";
	my $value_list = "";
	my $value_list_cus = "";


	foreach my $j (1 .. $i) {
		$parm_complete .= "T$j, I$j, N$j";

		$parm_complete .= ", " unless $j == $i;
		$parm_simple   .= "T$j, I$j";
		$parm_simple   .= ", " unless $j == $i;
		$parm_simple2c .= "T$j, I$j, #I$j";
		$parm_simple2c .= ", " unless $j == $i;
		$parm_simple_b   .= "T$j, I$j";
		$parm_simple_b   .= ", " unless $j == $i;
		$parm_simple2c_b .= "T$j, I$j";
		$parm_simple2c_b .= ", " unless $j == $i;



		$defs  .= "    T$j I$j;";
		$defs  .= "\n" unless $j == $i;


		$popul .= "    s->I$j = row[N$j].conv(T$j());";
		$popul .= "\n" unless $j == $i;




		$names .= "    N$j ";
		$names .= ",\n" unless $j == $i;
		$enums .= "    NAME##_##I$j";
		$enums .= ",\n" unless $j == $i;

		$field_list .= "    s << obj.manip << '`' << obj.obj->names[".($j-1)."] << '`'";
		$field_list .= " << obj.delim;\n" unless $j == $i;

		$value_list .= "    s << obj.manip << obj.obj->I$j";
		$value_list .= " << obj.delim;\n" unless $j == $i;

		$create_bool .= "    if (i$j) (*include)[".($j-1)."]=true;\n";

		$create_list .= "    if (i$j == NAME##_NULL) return;\n" unless $i == 1;
		$create_list .= "    (*include)[i$j]=true;\n";

		$value_list_cus .= "    if ((*obj.include)[".($j-1)."]) { \n";
		$value_list_cus .= "      if (before) s << obj.delim;\n" unless $j == 1;
		$value_list_cus .= "      s << obj.manip << obj.obj->I$j;\n";
		$value_list_cus .= "      before = true; \n" unless $j == $i;
		$value_list_cus .= "     } \n";

		$cus_field_list .= "    if ((*obj.include)[".($j-1)."]) { \n";
		$cus_field_list .= "      if (before) s << obj.delim;\n" unless $j == 1;
		$cus_field_list .= "      s << obj.manip << '`' << obj.obj->names[".($j-1)."] << '`';\n";
		$cus_field_list .= "      before = true; \n" unless $j == $i;
		$cus_field_list .= "     } \n";

		$cus_equal_list .= "    if ((*obj.include)[".($j-1)."]) { \n";
		$cus_equal_list .= "      if (before) s << obj.delim;\n" unless $j == 1;
		$cus_equal_list .= "      s << '`' << obj.obj->names[".($j-1)."] << '`' << obj.comp";
		$cus_equal_list .=        " << obj.manip << obj.obj->I$j;\n";
		$cus_equal_list .= "      before = true; \n" unless $j == $i;
		$cus_equal_list .= "     } \n";

		$equal_list .= "    s << '`' << obj.obj->names[".($j-1)."] << '`' << obj.comp";
		$equal_list .= " << obj.manip << obj.obj->I$j";
		$equal_list .= " << obj.delim;\n" unless $j == $i;

		$cusparms1  .= "bool i$j"         if     $j == 1;
		$cusparms1  .= "bool i$j = false" unless $j == 1;
		$cusparms1  .= ", " unless $j == $i;
		$cusparms11  .= "bool i$j" ;
		$cusparms11  .= ", " unless $j == $i;
		$cusparms2  .= "NAME##_enum i$j" if $j == 1;
		$cusparms2  .= "NAME##_enum i$j = NAME##_NULL" unless $j == 1;
		$cusparms2  .= ", " unless $j == $i;
		$cusparms22  .= "NAME##_enum i$j";
		$cusparms22  .= ", " unless $j == $i;
		$cusparmsv  .= "i$j";
		$cusparmsv  .= ", " unless $j == $i;


		$parmC .= "T$j, I$j";
		$parmC .= ", " unless $j == $max_data_members;
		$parmc .= "I$j";
		$parmc .= ", " unless $j == $max_data_members;
	}

	foreach my $j ($i + 1 .. $max_data_members) {
		$parmC .= "0, 0";
		$parmC .= ", " unless $j == $max_data_members;
		$parmc .= "0";
		$parmc .= ", " unless $j == $max_data_members;
	}




	print OUT << "---";
// ---------------------------------------------------
//                  Begin Create $i
// ---------------------------------------------------
---
	my $out = <<"---";
#define sql_create_complete_$i(NAME, CMP, CONTR, $parm_complete) 
	struct NAME; 

	enum NAME##_enum { 
$enums 
	,NAME##_NULL 
	}; 

	template <class Manip>
	class NAME##_value_list { 
	public: 
	const NAME* obj;
	const char* delim;
	Manip manip;
	public: 
	NAME##_value_list (const NAME* o, const char* d, Manip m) :
	obj(o), delim(d), manip(m) { } 
	};


	template <class Manip>
	class NAME##_##field_list {
	public: 
	const NAME* obj; 
	const char* delim;
	Manip manip;
	public: 
	NAME##_field_list (const NAME* o, const char* d, Manip m) :
	obj(o), delim(d), manip(m) { } 
	};

	template <class Manip>
	class NAME##_equal_list { 
	public: 
	const NAME* obj;
	const char* delim;
	const char* comp;
	Manip manip;
	public: 
	NAME##_equal_list (const NAME* o, const char* d, const char* c, Manip m) :
	obj(o), delim(d), comp(c), manip(m) { }
	};

	template <class Manip>
	class NAME##_cus_value_list {
	public:
	const NAME* obj;
	std::vector<bool> *include;
	bool del_vector;
	const char* delim;


	Manip manip;
	public: 
	~NAME##_cus_value_list () {if (del_vector) delete include;} 
	NAME##_cus_value_list (const NAME* o, const char* d, Manip m, $cusparms11);
	NAME##_cus_value_list (const NAME* o, const char* d, Manip m, $cusparms22); 
	NAME##_cus_value_list (const NAME* o, const char* d, Manip m ,std::vector<bool>* i) :
	obj(o), include(i), del_vector(false), delim(d), manip(m) { }
	};


	template <class Manip>
	class NAME##_cus_field_list { 
	public:
	const NAME* obj; 


	std::vector<bool> *include; 
	bool del_vector; 
	const char* delim;
	Manip manip;
	public: 
	~NAME##_cus_field_list () {if (del_vector) delete include;} 
	NAME##_cus_field_list (const NAME* o, const char* d, Manip m, $cusparms11); 
	NAME##_cus_field_list (const NAME* o, const char* d, Manip m, $cusparms22); 
	NAME##_cus_field_list (const NAME* o, const char* d, Manip m, std::vector<bool> *i) :
	obj(o), include(i), del_vector(false), delim(d), manip(m) { }
	};

	template <class Manip>
	class NAME##_cus_equal_list {
	public:
	const NAME* obj;
	std::vector<bool> *include;
	bool del_vector;
	const char* delim;
	const char* comp;
	Manip manip;
	public:
	~NAME##_##cus_equal_list () {if (del_vector) delete include;}
	NAME##_##cus_equal_list (const NAME* o, const char* d, const char* c, Manip m, $cusparms11); 
	NAME##_##cus_equal_list (const NAME* o, const char* d, const char* c, Manip m, $cusparms22); 
	NAME##_##cus_equal_list (const NAME* o, const char* d, const char* c, Manip m, std::vector<bool> *i) :
	obj(o), include(i), del_vector(false), delim(d), comp(c), manip(m) { }
	};

	template <mysqlpp::sql_dummy_type dummy> int sql_compare_##NAME(const NAME&, const NAME&);

	struct NAME {
$defs 
	NAME() : table_override_(0) { }
	NAME(const mysqlpp::Row& row);
	void set(const mysqlpp::Row &row);
	sql_compare_define_##CMP(NAME, $parmC)
	sql_construct_define_##CONTR(NAME, $parmC)
	static const char* names[];
	static void table(const char* t) { table_ = t; }
	const char* const table() const
			{ return table_override_ ? table_override_ : NAME::table_; }
	void instance_table(const char* t) { table_override_ = t; }

	NAME##_value_list<mysqlpp::quote_type0> value_list() const {
		return value_list(",", mysqlpp::quote);}
	NAME##_value_list<mysqlpp::quote_type0> value_list(const char* d) const {
		return value_list(d, mysqlpp::quote);}
	template <class Manip>
	NAME##_value_list<Manip> value_list(const char* d, Manip m) const;

	NAME##_field_list<mysqlpp::do_nothing_type0> field_list() const {
		return field_list(",", mysqlpp::do_nothing);}
	NAME##_field_list<mysqlpp::do_nothing_type0> field_list(const char* d) const {
		return field_list(d, mysqlpp::do_nothing);}
	template <class Manip>
	NAME##_field_list<Manip> field_list(const char* d, Manip m) const;


	NAME##_equal_list<mysqlpp::quote_type0> equal_list(const char* d = ",",
			const char* c = " = ") const
			{ return equal_list(d, c, mysqlpp::quote); }
	template <class Manip>
	NAME##_equal_list<Manip> equal_list(const char* d, const char* c, Manip m) const;

	/* cus_data */

	NAME##_cus_value_list<mysqlpp::quote_type0> value_list($cusparms1) const
			{ return value_list(",", mysqlpp::quote, $cusparmsv); }
	NAME##_cus_value_list<mysqlpp::quote_type0> value_list($cusparms2) const
			{ return value_list(",", mysqlpp::quote, $cusparmsv); }
	NAME##_cus_value_list<mysqlpp::quote_type0> value_list(std::vector<bool> *i) const
			{ return value_list(",", mysqlpp::quote, i); }
	NAME##_cus_value_list<mysqlpp::quote_type0> value_list(mysqlpp::sql_cmp_type sc) const
			{ return value_list(",", mysqlpp::quote, sc); }

	NAME##_cus_value_list<mysqlpp::quote_type0> value_list(const char* d, $cusparms1) const
			{ return value_list(d, mysqlpp::quote, $cusparmsv); }
	NAME##_cus_value_list<mysqlpp::quote_type0> value_list(const char* d, $cusparms2) const
			{ return value_list(d, mysqlpp::quote, $cusparmsv); }
	NAME##_cus_value_list<mysqlpp::quote_type0> value_list(const char* d,
			std::vector<bool> *i) const
			{ return value_list(d, mysqlpp::quote, i); }
	NAME##_cus_value_list<mysqlpp::quote_type0> value_list(const char* d,
			mysqlpp::sql_cmp_type sc) const
			{ return value_list(d, mysqlpp::quote, sc); }

	template <class Manip>
	NAME##_cus_value_list<Manip> value_list(const char* d, Manip m,
			$cusparms1) const;
	template <class Manip>
	NAME##_cus_value_list<Manip> value_list(const char* d, Manip m,
			$cusparms2) const;
	template <class Manip>
	NAME##_cus_value_list<Manip> value_list(const char* d, Manip m,
			std::vector<bool>* i) const;
	template <class Manip>
	NAME##_cus_value_list<Manip> value_list(const char* d, Manip m, 
			mysqlpp::sql_cmp_type sc) const;
	/* cus field */

	NAME##_cus_field_list<mysqlpp::do_nothing_type0> field_list($cusparms1) const 
			{ return field_list(",", mysqlpp::do_nothing, $cusparmsv); }
	NAME##_cus_field_list<mysqlpp::do_nothing_type0> field_list($cusparms2) const
			{ return field_list(",", mysqlpp::do_nothing, $cusparmsv); }
	NAME##_cus_field_list<mysqlpp::do_nothing_type0> field_list(std::vector<bool> *i) const
			{ return field_list(",", mysqlpp::do_nothing, i); }
	NAME##_cus_field_list<mysqlpp::do_nothing_type0> field_list(mysqlpp::sql_cmp_type sc) const
			{ return field_list(",", mysqlpp::do_nothing, sc); }

	NAME##_cus_field_list<mysqlpp::do_nothing_type0> field_list(const char* d,
			$cusparms1) const
			{ return field_list(d, mysqlpp::do_nothing, $cusparmsv); }
	NAME##_cus_field_list<mysqlpp::do_nothing_type0> field_list(const char* d,
			$cusparms2) const
			{ return field_list(d, mysqlpp::do_nothing, $cusparmsv); }
	NAME##_cus_field_list<mysqlpp::do_nothing_type0> field_list(const char* d,
			std::vector<bool>* i) const
			{ return field_list(d, mysqlpp::do_nothing, i); }
	NAME##_cus_field_list<mysqlpp::do_nothing_type0> field_list(const char* d,
			mysqlpp::sql_cmp_type sc) const
			{ return field_list(d, mysqlpp::do_nothing, sc); }


	template <class Manip>
	NAME##_cus_field_list<Manip> field_list(const char* d, Manip m,
			$cusparms1) const;
	template <class Manip>
	NAME##_cus_field_list<Manip> field_list(const char* d, Manip m,
			$cusparms2) const;
	template <class Manip>
	NAME##_cus_field_list<Manip> field_list(const char* d, Manip m,
			std::vector<bool> *i) const;
	template <class Manip>
	NAME##_cus_field_list<Manip> field_list(const char* d, Manip m,
			mysqlpp::sql_cmp_type sc) const;


	/* cus equal */

	NAME##_cus_equal_list<mysqlpp::quote_type0> equal_list($cusparms1) const
			{ return equal_list(",", " = ", mysqlpp::quote, $cusparmsv); }
	NAME##_cus_equal_list<mysqlpp::quote_type0> equal_list($cusparms2) const
			{ return equal_list(",", " = ", mysqlpp::quote, $cusparmsv); }
	NAME##_cus_equal_list<mysqlpp::quote_type0> equal_list(std::vector<bool>* i) const
			{ return equal_list(",", " = ", mysqlpp::quote, i); }
	NAME##_cus_equal_list<mysqlpp::quote_type0> equal_list(mysqlpp::sql_cmp_type sc) const
			{ return equal_list(",", " = ", mysqlpp::quote, sc); }

	NAME##_cus_equal_list<mysqlpp::quote_type0> equal_list(const char* d, $cusparms1) const
			{ return equal_list(d, " = ", mysqlpp::quote, $cusparmsv); }
	NAME##_cus_equal_list<mysqlpp::quote_type0> equal_list(const char* d, $cusparms2) const
			{ return equal_list(d, " = ", mysqlpp::quote, $cusparmsv); }
	NAME##_cus_equal_list<mysqlpp::quote_type0> equal_list(const char* d,
			std::vector<bool> *i) const
			{ return equal_list(d, " = ", mysqlpp::quote, i); }
	NAME##_cus_equal_list<mysqlpp::quote_type0> equal_list(const char* d,
			mysqlpp::sql_cmp_type sc) const
			{ return equal_list(d, " = ", mysqlpp::quote, sc); }

	NAME##_cus_equal_list<mysqlpp::quote_type0> equal_list(const char* d, const char* c,
			$cusparms1) const
			{ return equal_list(d, c, mysqlpp::quote, $cusparmsv); }
	NAME##_cus_equal_list<mysqlpp::quote_type0> equal_list(const char* d, const char* c,
			$cusparms2) const
			{ return equal_list(d, c, mysqlpp::quote, $cusparmsv); }
	NAME##_cus_equal_list<mysqlpp::quote_type0> equal_list(const char* d, const char* c,
			std::vector<bool> *i) const
			{ return equal_list(d, c, mysqlpp::quote, i); }
	NAME##_cus_equal_list<mysqlpp::quote_type0> equal_list(const char* d, const char* c,
			mysqlpp::sql_cmp_type sc) const
			{ return equal_list(d, c, mysqlpp::quote, sc); }

	template <class Manip>
	NAME##_cus_equal_list<Manip> equal_list(const char* d, const char* c, Manip m, 
						$cusparms1) const;
	template <class Manip>
	NAME##_cus_equal_list<Manip> equal_list(const char* d, const char* c, Manip m, 
						$cusparms2) const;
	template <class Manip>
	NAME##_cus_equal_list<Manip> equal_list(const char* d, const char* c, Manip m, 
						std::vector<bool> *i) const;
	template <class Manip>
	NAME##_cus_equal_list<Manip> equal_list(const char* d, const char* c, Manip m, 
						mysqlpp::sql_cmp_type sc) const;

	private:
	static const char* table_;
	const char* table_override_;

	};
	MYSQLPP_SSQLS_CONDITIONAL_STATICS(
		const char* NAME::names[] = {
			$names

		};
		const char* NAME::table_ = #NAME;
	)

	template <class Manip>
	NAME##_cus_value_list<Manip>::NAME##_cus_value_list
			(const NAME* o, const char* d, Manip m, $cusparms11)
	{
		delim = d;
		manip = m;
		del_vector = true;
		obj = o;
		include = new std::vector<bool>($i, false);
$create_bool
	}

	template <class Manip>
	NAME##_cus_value_list<Manip>::NAME##_cus_value_list
			(const NAME* o, const char* d, Manip m, $cusparms22)
	{

		delim = d;
		manip = m;
		del_vector = true;
		obj = o;
		include = new std::vector<bool>($i, false);
$create_list
	}

	template <class Manip>
	NAME##_cus_field_list<Manip>::NAME##_cus_field_list
			(const NAME* o, const char* d, Manip m, $cusparms11)
	{
		delim = d;
		manip = m;
		del_vector = true;
		obj = o;
		include = new std::vector<bool>($i, false);
$create_bool
	}

	template <class Manip>
	NAME##_cus_field_list<Manip>::NAME##_cus_field_list
			(const NAME* o, const char* d, Manip m, $cusparms22)
	{
		delim = d;
		manip = m;
		del_vector = true;
		obj = o;
		include = new std::vector<bool>($i, false);
$create_list
	}

	template <class Manip>
	NAME##_cus_equal_list<Manip>::NAME##_cus_equal_list
			(const NAME* o, const char* d, const char* c, Manip m, $cusparms11)
	{
		delim = d;
		comp = c;
		manip = m;
		del_vector = true;
		obj = o;
		include = new std::vector<bool>($i, false);
$create_bool
	}


	template <class Manip>
	NAME##_cus_equal_list<Manip>::NAME##_cus_equal_list
			(const NAME* o, const char* d, const char* c, Manip m, $cusparms22)
	{
		delim = d;
		comp = c;
		manip = m;
		del_vector = true;
		obj = o;
		include = new std::vector<bool>($i, false);
$create_list
	}

	template <class Manip>
	std::ostream& operator <<(std::ostream& s, const NAME##_value_list<Manip>& obj)
	{
$value_list;
		return s;
	}

	template <class Manip>
	std::ostream& operator <<(std::ostream& s, const NAME##_field_list<Manip>& obj)
	{
$field_list;
		return s;
	}

	template <class Manip>
	std::ostream& operator <<(std::ostream& s, const NAME##_equal_list<Manip>& obj)
	{
$equal_list;
		return s;
	}

	template <class Manip>
	std::ostream& operator <<(std::ostream& s, const NAME##_cus_value_list<Manip>& obj)
	{
		bool before = false;
$value_list_cus
		return s;
	}

	template <class Manip>
	std::ostream& operator <<(std::ostream& s, const NAME##_cus_field_list<Manip>& obj)
	{
		bool before = false;
$cus_field_list
		return s;
	}

	template <class Manip>
	std::ostream& operator <<(std::ostream& s, const NAME##_cus_equal_list<Manip>& obj)
	{
		bool before = false;
$cus_equal_list
		return s;
	}

	template <class Manip>
	inline NAME##_value_list<Manip> NAME::value_list(const char* d, Manip m) const
			{ return NAME##_value_list<Manip> (this, d, m); } 

	template <class Manip>
	inline NAME##_field_list<Manip> NAME::field_list(const char* d, Manip m) const
			{ return NAME##_field_list<Manip> (this, d, m); } 

	template <class Manip>
	inline NAME##_equal_list<Manip> NAME::equal_list(const char* d, const char* c, Manip m) const
			{ return NAME##_equal_list<Manip> (this, d, c, m); } 

	template <class Manip>

	inline NAME##_cus_value_list<Manip> NAME::value_list(const char* d, Manip m,
			$cusparms11) const
			{ return NAME##_cus_value_list<Manip> (this, d, m, $cusparmsv); }

	template <class Manip>
	inline NAME##_cus_field_list<Manip> NAME::field_list(const char* d, Manip m,
			$cusparms11) const
			{ return NAME##_cus_field_list<Manip> (this, d, m, $cusparmsv); }

	template <class Manip>
	inline NAME##_cus_equal_list<Manip> NAME::equal_list(const char* d, const char* c, Manip m,
			$cusparms11) const
			{ return NAME##_cus_equal_list<Manip> (this, d, c, m, $cusparmsv); } 

	template <class Manip>
	inline NAME##_cus_value_list<Manip> NAME::value_list(const char* d, Manip m,
			$cusparms22) const
			{ return NAME##_cus_value_list<Manip> (this, d, m, $cusparmsv); } 

	template <class Manip>
	inline NAME##_cus_field_list<Manip> NAME::field_list(const char* d, Manip m,
			$cusparms22) const
			{ return NAME##_cus_field_list<Manip> (this, d, m, $cusparmsv); } 

	template <class Manip>
	inline NAME##_cus_equal_list<Manip> NAME::equal_list(const char* d, const char* c, Manip m, 
			$cusparms22) const
			{ return NAME##_cus_equal_list<Manip> (this, d, c, m, $cusparmsv); } 

	template <class Manip>
	inline NAME##_cus_value_list<Manip> NAME::value_list(const char* d, Manip m,
			std::vector<bool> *i) const
			{ return NAME##_cus_value_list<Manip> (this, d, m, i); }

	template <class Manip>
	inline NAME##_cus_field_list<Manip> NAME::field_list(const char* d, Manip m,
			std::vector<bool> *i) const
			{ return NAME##_cus_field_list<Manip> (this, d, m, i); }

	template <class Manip>
	inline NAME##_cus_equal_list<Manip> NAME::equal_list(const char* d, const char* c, Manip m,
			std::vector<bool> *i) const
			{ return NAME##_cus_equal_list<Manip> (this, d, c, m, i); }

	template <class Manip>
	inline NAME##_cus_value_list<Manip> 
	NAME::value_list(const char* d, Manip m, mysqlpp::sql_cmp_type /*sc*/) const
			{ sql_compare_type_def_##CMP(NAME, value, NUM); }

	template <class Manip>
	inline NAME##_cus_field_list<Manip> 
	NAME::field_list(const char* d, Manip m, mysqlpp::sql_cmp_type /*sc*/) const
			{ sql_compare_type_def_##CMP(NAME, field, NUM); }

	template <class Manip>
	inline NAME##_cus_equal_list<Manip> 
	NAME::equal_list(const char* d, const char* c, Manip m, mysqlpp::sql_cmp_type /*sc*/) const
			{ sql_compare_type_defe_##CMP(NAME, equal, NUM); }

	template <mysqlpp::sql_dummy_type dummy>
	void populate_##NAME(NAME *s, const mysqlpp::Row &row)
	{
		mysqlpp::NoExceptions ignore_schema_mismatches(row);
$popul
	}

	inline NAME::NAME(const mysqlpp::Row& row) :
	table_override_(0)
			{ populate_##NAME<mysqlpp::sql_dummy>(this, row); }
	inline void NAME::set(const mysqlpp::Row& row)
	{
		table_override_ = 0;
		populate_##NAME<mysqlpp::sql_dummy>(this, row);
	}

	sql_COMPARE__##CMP(NAME, $parmc )

---
print OUT &prepare($out);


#
# short cut defs
#

print OUT << "---";
#define sql_create_$i(NAME, CMP, CONTR, $parm_simple) \\
		sql_create_complete_$i(NAME, CMP, CONTR, $parm_simple2c) \\

// ---------------------------------------------------
//                  End Create $i
// ---------------------------------------------------

---

}


print OUT << "---";

} // end namespace mysqlpp

#endif // !defined(MYSQLPP_SSQLS_H)

---


sub prepare {
	local $_ = $_[0];
	s/\n+$//;
	s/\n[\n ]*\n/\n/g; 
	s/\n+/\\\n/g;
	$_ .= "\n\n";
	return $_;
}

Changes to lib/mystring.h.


1

2


3





4


5




6







7





8






9





10




11



12



13





14


15
16


17




18



19









20
21


22
23
24
25



26




27


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
56

57

58


59



60

















61

62




63

64


65



66




67


68


69

70


71

72
73














74

75







76


77




78




79




80


81
82

83
84




85
86


87

88
89

90



91

92

93




94
95

96



97






98

99




100
101

102










103



104



105


106


107




108
109


110


111

112
113

114

115


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





191

192



193


194
195
196
197
198
199

200


201



202

203





204


205

206



207

208


209
210



211


212

213
214




215


216




217



218






219

220


221


222


223



224


225

226



227
228
229

230

231







232



233



234







































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





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

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


372
373

374


375



376


377





378
379



380




381


382
383
384

385






386
387




388




389



390


391



392

393



394
395

396

397

398
399

400




401


402



403


404





405


406



407


408
409

410


411











412


413

414

415


416
417

418

419


420
421

























422
423
424
425
426
427
428








429









430
431




432





433
434
435







436




437


438


439


440



441




442






443





444





445











446
447


448





449








450







451


452




453
454


455
456
457
458







459
460





461





462

463

464
465


466
467


468







469



470
471





472






473



474


475


476


477




478


479


480


481



482



483





484




485




486




487



488



489




490
491

492
493


494


495



496




497


498


499


500


501

502


503


504


























505


506




507




508


509



510








511




512




513





514


515
516
517
518


519


520


521




522


523

524




525




526




527


528
529

530



531


532


533


534

535


536



537

538
539

540





541
















542

543
544

545





546

547

548

549



550


551



552


553

















554



555


556


557


558
559

560


561


562



563

564



565


566


567






568



569




570


571




572


573


574



575



576






577
578

579





580




581
582

583



584

585


586

587

588

589
590






















591



592

593


594


595
596

597


598


599

600























601
602

603




604


605


606


607

608


609



610

611


612


613




614

615

616
617




618

619

620

621
622

623


624



625




























626

627


628
629

630



631




632



633



634


635


636



637









638
639

640




641







642






643

644



645
646

647


648




649

650





651
652

653


654



655
656

657


658


659




























660


661

662



663


664
665

666


667

668


669

670

671

















672


673
674

675


676






677







678
679

680


681



682

683
684

685




686


687

688























689

690

691






692

693
694
































695
696
697
698
699

700
701
702
703
704


















705
706
707
708
709
710
711
712
713








714












715

716
717











718
719


















720

721






722

723









724

725
726











727
728
729
730
731
732
733
734












735

736







737


738


739
740

741


742

743




744

745





746

747


748




749
750

751



752
753
754











755

756

757







758

759
760



761
762
763

764

765






766

767











768

769







770

/// \file mystring.h

/// \brief Declares String class, MySQL++'s generic std::string-like


/// class, used for holding data received from the database server.








/***********************************************************************




 Copyright (c) 1998 by Kevin Atkinson, (c) 1999-2001 by MySQL AB, and







 (c) 2004-2008 by Educational Technology Resources, Inc.  Others may





 also hold copyrights on code in this file.  See the CREDITS.txt file






 in the top directory of the distribution for details.










 This file is part of MySQL++.







 MySQL++ is free software; you can redistribute it and/or modify it





 under the terms of the GNU Lesser General Public License as published


 by the Free Software Foundation; either version 2.1 of the License, or
 (at your option) any later version.







 MySQL++ is distributed in the hope that it will be useful, but WITHOUT



 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or









 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
 License for more details.



 You should have received a copy of the GNU Lesser General Public
 License along with MySQL++; if not, write to the Free Software
 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301



 USA




***********************************************************************/



#if !defined(MYSQLPP_MYSTRING_H)
#define MYSQLPP_MYSTRING_H






#include "common.h"












#include "datetime.h"


#include "exceptions.h"
#include "null.h"






#include "sql_buffer.h"






#include <string>
#include <sstream>


#include <limits>






#include <stdlib.h>


#include <string.h>







namespace mysqlpp {









#if !defined(DOXYGEN_IGNORE)






// Doxygen will not generate documentation for this section.








namespace detail

{


	template<typename T, bool is_signed = std::numeric_limits<T>::is_signed>

	struct conv_promotion;


	template<>

	struct conv_promotion<float>

	{


		typedef double type;



	};



















	template<>




	struct conv_promotion<double>

	{


		typedef double type;



	};







#	if !defined(NO_LONG_LONGS)


	template<>

	struct conv_promotion<unsigned long long>


	{

		typedef unsigned long long type;
	};
















	template<>







	struct conv_promotion<long long>


	{




		typedef long long type;




	};




#	endif



	// preserve existing behaviour, char converted as signed long

	template<>
	struct conv_promotion<char>




	{
		typedef long type;


	};


	// all other types use signed/unsigned long





	template<typename T>

	struct conv_promotion<T, true>

	{




		typedef long type;
	};





	template<typename T>






	struct conv_promotion<T, false>

	{




		typedef unsigned long type;
	};

} // namespace detail














class MYSQLPP_EXPORT SQLTypeAdapter;



#endif // !defined(DOXYGEN_IGNORE)





/// \brief A std::string work-alike that can convert itself from SQL




/// text data formats to C++ data types.
///


/// This class is an intermediate form for a SQL field, normally


/// converted to a more useful native C++ type, not used directly.

/// The only exception is in dealing with BLOB data, which stays in
/// String form for efficiency and to avoid corrupting the data with

/// facile conversions.  Even then, it's best to use it through the 

/// typedef aliases like sql_blob in sql_types.h, in case we later


/// change this underlying representation.

///


/// String's implicit conversion operators let you can use these

/// objects naturally:

///

/// \code String("12.86") + 2.0 \endcode
///


/// That will give you 14.86 (approximately) as you expect, but be

/// careful not to get tripped up by C++'s type conversion rules.  If


/// you had said this instead:

/// 




/// \code String("12.86") + 2 \endcode
/// 




/// the result would be 14 because 2 is an integer, and C++'s type
/// conversion rules put the String object in an integer context.
///


/// You can disable the operator overloads that allow these things by



/// defining MYSQLPP_NO_BINARY_OPERS.


///


/// This class also has some basic information about the type of data


/// stored in it, to allow it to do the conversions more intelligently
/// than a trivial implementation would allow.







class MYSQLPP_EXPORT String





{

public:



	/// \brief Type of the data stored in this object, when it is not





	/// equal to SQL null.
	typedef const char value_type;







	/// \brief Type of "size" integers









	typedef size_t size_type;












	/// \brief Type of iterators

	typedef const char* const_iterator;












































	/// \brief Same as const_iterator because the data cannot be


	/// changed.

	typedef const_iterator iterator;








#if !defined(DOXYGEN_IGNORE)

// Doxygen will not generate documentation for this section.


	typedef int difference_type;






	typedef const char* const_pointer;



	typedef const_pointer pointer;



#endif // !defined(DOXYGEN_IGNORE)















	/// \brief Default constructor








	///



	/// An object constructed this way is essentially useless, but



	/// sometimes you just need to construct a default object.



	String() :

	buffer_()




	{

	}






	/// \brief Copy ctor






	///
	/// \param other the other String object




	///




	/// This ctor only copies the pointer to the other String's data

	/// buffer and increments its reference counter.  If you need a






	/// deep copy, use one of the ctors that takes a string.
	String(const String& other) :

	buffer_(other.buffer_)





	{







	}










	/// \brief Full constructor.
	///


	/// \param str the string this object represents, or 0 for SQL null



	/// \param len the length of the string; embedded nulls are legal
	/// \param type MySQL type information for data within str




	/// \param is_null string represents a SQL null, not literal data

	///





	/// The resulting object will contain a copy of the string buffer.

	/// The buffer will actually be 1 byte longer than the value given



	/// for \c len, to hold a null terminator for safety.  We do this


	/// because this ctor may be used for things other than
	/// null-terminated C strings.  (e.g. BLOB data)
	explicit String(const char* str, size_type len,
			mysql_type_info type = mysql_type_info::string_type,
			bool is_null = false) :
	buffer_(new SQLBuffer(str, len, type, is_null))

	{


	}





	/// \brief C++ string version of full ctor





	///


	/// \param str the string this object represents, or 0 for SQL null

	/// \param type MySQL type information for data within str



	/// \param is_null string represents a SQL null, not literal data

	///


	/// The resulting object will contain a copy of the string buffer.
	explicit String(const std::string& str,



			mysql_type_info type = mysql_type_info::string_type,


			bool is_null = false) :

	buffer_(new SQLBuffer(str.data(), static_cast<size_type>(str.length()),
			type, is_null))




	{


	}








	/// \brief Null-terminated C string version of full ctor






	///

	/// \param str the string this object represents, or 0 for SQL null


	/// \param type MySQL type information for data within str


	/// \param is_null string represents a SQL null, not literal data


	///



	/// The resulting object will contain a copy of the string buffer.


	explicit String(const char* str,

			mysql_type_info type = mysql_type_info::string_type,



			bool is_null = false) :
	buffer_(new SQLBuffer(str, static_cast<size_type>(strlen(str)),
			type, is_null))

	{

	}











	/// \brief Destroy string



	~String() { }









































	/// \brief Assign raw data to this object
	///
	/// This parallels the ctor with the same parameters, for when you


	/// must do a 2-step create, or when you want to reassign the data 



	/// without creating a String temporary to get around the fact




	/// that operator=() can only take one parameter.
	void assign(const char* str, size_type len,


			mysql_type_info type = mysql_type_info::string_type,




			bool is_null = false)





	{





		buffer_ = new SQLBuffer(str, len, type, is_null);





	}




	/// \brief Assign a C++ string to this object




	///




	/// This parallels the ctor with the same parameters, for when you






	/// must do a 2-step create, or when you want to reassign the data 
	/// without creating a String temporary to get around the fact

	/// that operator=() can only take one parameter.
	void assign(const std::string& str,
			mysql_type_info type = mysql_type_info::string_type,
			bool is_null = false)
	{








		buffer_ = new SQLBuffer(str.data(),






				static_cast<size_type>(str.length()), type, is_null);

	}








	/// \brief Assign a C string to this object

	///


	/// This parallels the ctor with the same parameters, for when you




	/// must do a 2-step create, or when you want to reassign the data 


	/// without creating a String temporary to get around the fact



	/// that operator=() can only take one parameter.





	void assign(const char* str,




			mysql_type_info type = mysql_type_info::string_type,


			bool is_null = false)



	{

		buffer_ = new SQLBuffer(str, static_cast<size_type>(strlen(str)),
				type, is_null);


	}





	/// \brief Return a character within the string.








	///



	/// \throw mysqlpp::BadIndex if the row is not initialized or there
	/// are less than \c i fields in the row.

	char at(size_type pos) const;






	/// \brief Return iterator pointing to the first character of



	/// the string


	const_iterator begin() const { return data(); }

















	/// \brief Return a const pointer to the string data.



	const char* c_str() const { return data(); }






	

#if defined(MYSQLPP_PLATFORM_VISUAL_CPP)
// Squish VC++ warning about "possible loss of data" for these conversions

#   pragma warning(disable: 4244)


#endif



























	/// \brief Template for converting the column data to most any




	/// numeric data type.

	template <class Type>




	Type conv(Type) const





	{
		// Conversions are done using one of double/long/ulong/llong/ullong


		// so we call a helper function to do the work using that type.






		// This reduces the amount of template code instantiated.



		typedef typename detail::conv_promotion<Type>::type conv_type;



		return do_conv<conv_type>(typeid(Type).name());

	}





#if defined(MYSQLPP_PLATFORM_VISUAL_CPP)

#   pragma warning(default: 4244)


#endif










































	/// \brief Overload of conv() for types wrapped with Null<>

	///
	/// If the String object was initialized with some string we

	/// recognize as a SQL null, we just return a copy of the global

	/// 'null' object converted to the requested type.  Otherwise, we

	/// return the String's value wrapped in the Null<> template.
	template <class T, class B>



	Null<T, B> conv(Null<T, B>) const






	{


		if (is_null()) {
			return Null<T, B>(null);


		}





		else {
			return Null<T, B>(conv(T()));





		}



	}






	/// \brief Lexically compare this string to another.





	///


	/// \param other string to compare against this one
	///





	/// \see compare(size_type, size_type, const char*)
	int compare(const String& other) const;




	/// \brief Lexically compare this string to another.
	///


	/// \param other string to compare against this one

	///


	/// \see compare(size_type, size_type, const char*)


	int compare(const std::string& other) const;






	/// \brief Lexically compare this string to another.

	///









	/// \param pos position within this string to begin comparison


	/// \param num maximum number of characters within this string to


	/// use in comparison



	/// \param other string to compare against this one


	///



	/// \see compare(size_type, size_type, const char*)


	int compare(size_type pos, size_type num, std::string& other) const;




















	/// \brief Lexically compare this string to another.





	///



	/// \param other string to compare against this one




	///


	/// \see compare(size_type, size_type, const char*)


	int compare(const char* other) const;




















	/// \brief Lexically compare this string to another.

	///
	/// \param pos position within this string to begin comparison

	/// \param num maximum number of characters within this string to

	/// use in comparison



	/// \param other string to compare against this one





	///
	/// \retval < 0 if this string is lexically "less than" other

	/// \retval 0 if this string is equal to other


	/// \retval > 0 if this string is lexically "greater than" other


	int compare(size_type pos, size_type num, const char* other) const;























	/// \brief Raw access to the underlying buffer, with no C string


	/// interpretation.
	const char* data() const;




	/// \brief Returns true if size() == 0



	bool empty() const { return size() == 0; }


	





	/// \brief Return iterator pointing to one past the last character
	/// of the string.



	const_iterator end() const;







	/// \brief Returns true if data of this type should be escaped, false
	/// otherwise.
	bool escape_q() const;








	/// \brief Returns true if this object is a SQL null.
	bool is_null() const;









	/// \brief Set a flag indicating that this object is a SQL null.



	void it_is_null();






	/// \brief Return number of bytes in the string

	///



	/// Note that this doesn't count the number of \b characters in the
	/// string.  If your database is configured to use an 8-bit character

	/// set, this is a distinction without a difference.  But, if you're

	/// using UTF-8 in the database, you will need to "widen" the UTF-8

	/// data to use a fixed-size character set like UCS-2 and count the
	/// characters that way.  You might use std::wstring, for example.

	size_type length() const;




	


	/// \brief Return the maximum number of characters in the string.



	///


	/// Because this is a \c const string, this is just an alias for





	/// size(); its size is always equal to the amount of data currently


	/// stored.



	size_type max_size() const { return size(); }



	/// \brief Returns true if data of this type should be quoted, false

	/// otherwise.


	bool quote_q() const;














	/// \brief Return number of bytes in string

	///

	/// See commentary for length() about the difference between bytes


	/// and characters.
	size_type size() const { return length(); }

	

	/// \brief Returns a copy of our internal string without leading


	/// blanks.
	void strip_leading_blanks(std::string& s) const

























	{
		const char* pc = data();
		if (pc) {
			size_type n = length();
			while (n && (*pc == ' ')) {
				++pc;
				--n;








			}










			s.assign(pc, n);




		}





		else {
			s.clear();
		}







	}







	/// \brief Copies this object's data into a C++ string.


	///


	/// If you know the data doesn't contain null characters (i.e. it's



	/// a typical string, not BLOB data), it's more efficient to just




	/// assign this object to anything taking \c const \c char*.  (Or






	/// equivalently, call the \c data() method.)  This copies a pointer





	/// to a buffer instead of copying the buffer's contents.





	void to_string(std::string& s) const;












	/// \brief Get this object's current MySQL type.


	mysql_type_info type() const





	{








		return buffer_ ? buffer_->type() : mysql_type_info::string_type;







	}







	/// \brief Assignment operator, from C++ string
	String& operator =(const std::string& rhs)


	{
		buffer_ = new SQLBuffer(rhs.data(),
				static_cast<size_type>(rhs.length()),
				mysql_type_info::string_type, false);








		return *this;





	}







	/// \brief Assignment operator, from C string

	///
	/// This creates a copy of the entire string, not just a copy of


	/// the pointer.
	String& operator =(const char* str)


	{







		buffer_ = new SQLBuffer(str,



				static_cast<size_type>(strlen(str)),
				mysql_type_info::string_type, false);












		return *this;



	}





	/// \brief Assignment operator, from other String


	///




	/// This only copies the pointer to the other String's data


	/// buffer and increments its reference counter.  If you need a


	/// deep copy, assign a string to this object instead.


	String& operator =(const String& other)



	{



		buffer_ = other.buffer_;










		return *this;




	}








	/// \brief Equality comparison operator



	///




	/// For comparing this object to any of the data types we have a
	/// compare() overload for.

	template <typename T>
	bool operator ==(const T& rhs) const


	{


		return compare(rhs) == 0;



	}







	/// \brief Equality comparison operator


	///


	/// For checking object against MySQL++'s global \c null constant


	bool operator ==(const mysqlpp::null_type&) const

	{


		return is_null();


	}





























	/// \brief Inequality comparison operator




	///




	/// For comparing this object to any of the data types we have a


	/// compare() overload for.



	template <typename T>








	bool operator !=(const T& rhs) const




	{




		return compare(rhs) != 0;





	}



	/// \brief Inequality comparison operator
	///
	/// For checking object against MySQL++'s global \c null constant


	bool operator !=(const mysqlpp::null_type&) const


	{


		return !is_null();




	}




	/// \brief Return a character within the string.




	///




	/// This function is just syntactic sugar, wrapping the at() method.




	///


	/// \throw mysqlpp::BadIndex if the string is not initialized or there
	/// are less than \c i fields in the string.

	char operator [](size_type pos) const { return at(pos); }






	/// \brief Returns a const char pointer to the object's raw data


	operator const char*() const { return data(); }


	

	/// \brief Converts this object's string data to a signed char


	operator signed char() const



			{ return conv(static_cast<signed char>(0)); }

	
	/// \brief Converts this object's string data to an unsigned char

	operator unsigned char() const





			{ return conv(static_cast<unsigned char>(0)); }
















	

	/// \brief Converts this object's string data to an int
	operator int() const

			{ return conv(static_cast<int>(0)); }





	

	/// \brief Converts this object's string data to an unsigned int

	operator unsigned int() const

			{ return conv(static_cast<unsigned int>(0)); }



	


	/// \brief Converts this object's string data to a short int



	operator short int() const


			{ return conv(static_cast<short int>(0)); }

















	



	/// \brief Converts this object's string data to an unsigned short


	/// int


	operator unsigned short int() const


			{ return conv(static_cast<unsigned short int>(0)); }
	

	/// \brief Converts this object's string data to a long int


	operator long int() const


			{ return conv(static_cast<long int>(0)); }



	

	/// \brief Converts this object's string data to an unsigned long



	/// int


	operator unsigned long int() const


			{ return conv(static_cast<unsigned long int>(0)); }






	



#if !defined(NO_LONG_LONGS)




	/// \brief Converts this object's string data to the platform-


	/// specific 'longlong' type, usually a 64-bit integer.




	operator longlong() const


			{ return conv(static_cast<longlong>(0)); }


	



	/// \brief Converts this object's string data to the platform-



	/// specific 'ulonglong' type, usually a 64-bit unsigned integer.






	operator ulonglong() const
			{ return conv(static_cast<ulonglong>(0)); }

#endif





	




	/// \brief Converts this object's string data to a float
	operator float() const

			{ return conv(static_cast<float>(0)); }



	

	/// \brief Converts this object's string data to a double


	operator double() const

			{ return conv(static_cast<double>(0)); }

	

	/// \brief Converts this object's string data to a bool
	operator bool() const { return buffer_ ? atoi(c_str()) : false; }


























	/// \brief Converts this object's string data to a mysqlpp::Date

	operator Date() const { return buffer_ ? Date(*this) : Date(); }





	/// \brief Converts this object's string data to a mysqlpp::DateTime
	operator DateTime() const

			{ return buffer_ ? DateTime(*this) : DateTime(); }





	/// \brief Converts this object's string data to a mysqlpp::Time

	operator Time() const { return buffer_ ? Time(*this) : Time(); }
























	/// \brief Converts the String to a nullable data type

	///




	/// This is just an implicit version of conv(Null<T, B>)


	template <class T, class B>


	operator Null<T, B>() const { return conv(Null<T, B>()); }




private:


	/// \brief Do the actual numeric conversion via @p Type.



	template <class Type>

	Type do_conv(const char* type_name) const


	{


		if (buffer_) {




			std::stringstream buf;

			buf.write(data(), static_cast<std::streamsize>(length()));

			buf.imbue(std::locale::classic()); // "C" locale
			Type num = Type();




			

			if (buf >> num) {

				char c;

				if (!(buf >> c)) {
					// Nothing left in buffer, so conversion complete,

					// and thus successful.


					return num;



				}






























				if (c == '.' &&


						(typeid(Type) != typeid(float)) &&
						(typeid(Type) != typeid(double))) {

					// Conversion stopped on a decimal point -- locale



					// doesn't matter to MySQL -- so only way to succeed




					// is if it's an integer and everything following



					// the decimal is inconsequential.



					c = '0';	// handles '.' at end of string


					while (buf >> c && c == '0') /* spin */ ;


					if (buf.eof() && c == '0') {



						return num;  // only zeros after decimal point









					}
				}

			}




			else if (buf.eof()) {







				return num;  // nothing to convert, return default value






			}





			throw BadConversion(type_name, data(), 0, length());
		}

		else {


			return 0;




		}

	}






	RefCountedBuffer buffer_;	///< reference-counted data buffer




	friend class SQLTypeAdapter;



};


MYSQLPP_EXPORT std::ostream& operator <<(std::ostream& o,


		const String& in);


































#if !defined(MYSQLPP_NO_BINARY_OPERS) && !defined(DOXYGEN_IGNORE)

// Ignore this section is MYSQLPP_NO_BINARY_OPERS is defined, or if this



// section is being parsed by Doxygen.  In the latter case, it's ignored


// because Doxygen doesn't understand it correctly, and we can't be
// bothered to explain it to Doxygen.




#define oprsw(opr, other, conv) \

	inline other operator opr (String x, other y) \


			{ return static_cast<conv>(x) opr y; } \

	inline other operator opr (other x, String y) \

			{ return x opr static_cast<conv>(y); }




















#define operator_binary(other, conv) \
	oprsw(+, other, conv) \

	oprsw(-, other, conv) \


	oprsw(*, other, conv) \






	oprsw(/, other, conv)








#define operator_binary_int(other, conv) \

	operator_binary(other, conv) \


	oprsw(%, other, conv) \



	oprsw(&, other, conv) \

	oprsw(^, other, conv) \
	oprsw(|, other, conv) \

	oprsw(<<, other, conv) \




	oprsw(>>, other, conv)




// Squish more complaints about possible loss of data























#if defined(MYSQLPP_PLATFORM_VISUAL_CPP)

#	pragma warning(disable: 4244)

#endif








operator_binary(float, double)
operator_binary(double, double)

































operator_binary_int(char, long int)
operator_binary_int(int, long int)
operator_binary_int(short int, long int)
operator_binary_int(long int, long int)


operator_binary_int(unsigned char, unsigned long int)
operator_binary_int(unsigned int, unsigned long int)
operator_binary_int(unsigned short int, unsigned long int)
operator_binary_int(unsigned long int, unsigned long int)



















#if defined(MYSQLPP_PLATFORM_VISUAL_CPP)
#	pragma warning(default: 4244)
#endif

#if !defined(NO_LONG_LONGS)
operator_binary_int(longlong, longlong)
operator_binary_int(ulonglong, ulonglong)
#endif // !defined(NO_LONG_LONGS)








#endif // !defined(MYSQLPP_NO_BINARY_OPERS) && !defined(DOXYGEN_IGNORE)















#if !defined(DOXYGEN_IGNORE)











// Doxygen isn't smart enough to recognize these template
// specializations.  Maybe it's the MYSQLPP_EXPORT tags?




















/// \brief Specialization of String::conv<Type>() for bool






///

/// We can either do it this way, or define "\c strtob()" (string to









/// bool, like \c strtol(), \c strtod()...) so we can use

/// internal_string_to_number_proxy.
template <> MYSQLPP_EXPORT bool String::conv(bool) const;












/// \brief Specialization of String::conv<Type>() for String
///
/// Yes, I hear you crying, "WTF!?  Why does String need to be able to
/// convert itself to String?"  SSQLSes with BLOB columns, that's why.
///
/// SSQLSes populate their data members from the raw field data by
/// calling row["fieldname"].conv().  The raw field data is stored in a












/// String, and the MySQL++ native BLOB type is String.  Since we're

/// dealing with generated code, we need this specialization which hand-







/// written code wouldn't need.  Prove the truth of this to yourself by


/// removing this and counting how many pieces examples/cgi_jpeg.cpp


/// breaks into.
template <> MYSQLPP_EXPORT String String::conv(String) const;




/// \brief Specialization of String::conv<Type>() for C++ strings

template <> MYSQLPP_EXPORT std::string String::conv(std::string) const;






/// \brief Specialization of String::conv<Type>() for mysqlpp::Date





///

/// This is necessary because as of MySQL++ v3, Date no longer has an


/// implicit conversion ctor from String, and SSQLS uses conv() instead




/// of the C++ type conversion system anyway.
template <> MYSQLPP_EXPORT Date String::conv(Date) const;





/// \brief Specialization of String::conv<Type>() for mysqlpp::DateTime
///
/// This is necessary because as of MySQL++ v3, DateTime no longer has











/// an implicit conversion ctor from String, and SSQLS uses conv()

/// instead of the C++ type conversion system anyway.

template <> MYSQLPP_EXPORT DateTime String::conv(DateTime) const;









/// \brief Specialization of String::conv<Type>() for mysqlpp::Time
///



/// This is necessary because as of MySQL++ v3, Time no longer has an
/// implicit conversion ctor from String, and SSQLS uses conv() instead
/// of the C++ type conversion system anyway.

template <> MYSQLPP_EXPORT Time String::conv(Time) const;








#endif // !defined(DOXYGEN_IGNORE)













} // end namespace mysqlpp









#endif // !defined(MYSQLPP_MYSTRING_H)
>
|
>
|
>
>
|
>
>
>
>
>

>
>
|
>
>
>
>
|
>
>
>
>
>
>
>
|
>
>
>
>
>
|
>
>
>
>
>
>
|
>
>
>
>
>

>
>
>
>
|
>
>
>

>
>
>
|
>
>
>
>
>
|
>
>
|
|
>
>

>
>
>
>
|
>
>
>
|
>
>
>
>
>
>
>
>
>
|
<
>
>

<
<
|
>
>
>
|
>
>
>
>
|
>
>

<
<
>
>
>
>
>

<
>
>
>
>
>
>
>
>

>
>
>
|
>
>
|
|
>
>
>
>
>
>
|
>
>

>
>
>
|
|
>
>
|
>
>
>

>
>
|
>
>
|

>
>
>
>
>
>
|
>
>
>

>
>
>
>
>
|
>
>
>
>
>
>
|
>
>

>
>
>
>
>
|
>
|
>
>
|
>
|
>

|
>
|
>
|
>
>
|
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

>
|
>
>
>
>
|
>
|
>
>
|
>
>
>
|
>
>
>
>

>
>
|
>
>
|
>
|
>
>
|
>
|
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>

>
|
>
>
>
>
>
>
>
|
>
>
|
>
>
>
>
|
>
>
>
>
|
>
>
>
>
|
>
>

|
>
|
<
>
>
>
>
|
|
>
>
|
>

|
>

>
>
>
|
>
|
>
|
>
>
>
>
|
|
>

>
>
>
|
>
>
>
>
>
>
|
>
|
>
>
>
>
|
|
>
|
>
>
>
>
>
>
>
>
>
>

>
>
>
|
>
>
>
|
>
>

>
>
|
>
>
>
>
|
<
>
>
|
>
>
|
>
|
|
>
|
>
|
>
>
|
>
|
>
>
|
>
|
>
|
>
|
<
>
>
|
>
|
>
>
|
>
|
>
>
>
>
|
<
>
>
>
>
|
|
<
>
>
|
>
>
>
|
>
>
|
>
>
|
>
>
|
|
>
>
>

>
>
>
|
>
>
>
>
>
|
>
|
>
>
>
|
>
>
>
>
>
|
|
>

>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
|
>
>
>
>
>
>
>

>
>
>
>
|
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

>
>
|
>
>
|
>
|
>
>
>
>
>

>
>
|
>
|
>
>
|
>
>
>
>
>
>
|
>
>
>
|
>
>
>
|
>
>
>
>
>
>
>
>

>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
|
>
>
>
|
>
>
>
|
>
>
>
|
>
|
>
>
>
>
|
>
|
>
>
>
>

>
|
>
>
>
>
>
>
|
|
>
>
>
>
|
>
>
>
>
|
>
|
>
>
>
>
>
>
|
|
>
|
>
>
>
>
>
|
>
>
>
>
>
>
>
|
>
>
>
>
>

>
>
>
>
|
|
>
>
|
>
>
>
|
|
>
>
>
>
|
>
|
>
>
>
>
>
|
>
|
>
>
>
|
>
>
|
<
<
<
<
<
>
|
>
>
|
>
>
>

>
|
>
>
>
>
>
|
>
>
|
>
|
>
>
>
|
>
|
>
>
|
|
>
>
>
|
>
>
|
>
|
<
>
>
>
>
|
>
>
|
>
>
>
>

>
>
>
|
>
>
>
>
>
>
|
>
|
>
>
|
>
>
|
>
>
|
>
>
>
|
>
>
|
>
|
>
>
>
|
<
<
>
|
>
|
>
>
>
>
>
>
>

>
>
>
|
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

>
|
<
|
>
>
|
>
>
>
|
>
>
>
>
|
|
>
>
|
>
>
>
>
|
>
>
>
>
>
|
>
>
>
>
>
|
>
>
>
>
>
|
>

>
>
|
>
>
>
>
|
>
>
>
>
|
>
>
>
>
>
>
|
<
>
|
<
<
|
|
>
>
>
>
>
>
>
>
|
>
>
>
>
>
>
|
>
|
>
>
>
>
>
>

>
|
>
|
>
>
|
>
>
>
>
|
>
>
|
>
>
>
|
>
>
>
>
>
|
>
>
>
>
|
>
>
|
>
>
>
|
>
|
<
>
>
|
>

>
>
>
|
>
>
>
>
>
>
>
>
|
>
>
>
|
|
>
|
>
>

>
>
>
|
>
>
>
|
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>

>
>
>
>
|
>
>
>
|
>
>
>
>
>
>
|
>
|
|
>
|
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

>
>
|
>
>
>
>
|
>
|
>
>
>
>
|
>
>
>
>
>
|
|
>
>
|
>
>
>
>
>
>
|
>
>
>
|
>
>
>
|
>
|
>
>

>
>
|
>
|
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

>
|
>
|
|
>
|
>
|
>
|
|
>
>
>
|
>
>
>
>
>
>
|
>
>
|
|
>
>
|
>
>
>
>
>
|
|
>
>
>
>
>
|
>
>
>
|
>
>

>
>
>
|
>
>
>
>
>
|
>
>
|
|
>
>
>
>
>
|
|
>

>
>
|
<
>
>
|
>
|
>
>
|
>
>
|
>
>
>
>
>

|
>
|
>
>
>
>
>
>
>
>
>
|
>
>
|
>
>
|
>
>
>
|
>
>
|
>
>
>
|
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>

>
>
>
>
>
>
>
|
>
>
>
>
>
|
>
>
>
|
>
>
>
>
|
>
>
|
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

>
>
|
>
|
|
>
|
>
|
>
>
>
|
>
>
>
>
>
|
|
>
|
>
>
|
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

>
>
>
>
|
>
>
|
|
>

>
>
|
>
>
>
|
>
>
|
>
>
>
>
>
|
|
>
>
>
|
>
>
>
>

>
>
|
|
<
>

>
>
>
>
>
>
|
|
>
>
>
>

>
>
>
>
|
>
>
>
|
>
>

>
>
>
|
>
|
>
>
>
|
|
>
|
>
|
>
|
|
>
|
>
>
>
>
|
>
>
|
>
>
>
|
>
>
|
>
>
>
>
>
|
>
>
|
>
>
>
|
>
>

|
>
|
>
>
|
>
>
>
>
>
>
>
>
>
>
>

>
>
|
>
|
>
|
>
>
|
|
>
|
>
|
>
>
|
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
|
|
|
|
|
|
>
>
>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>

<
>
>
>
>
|
>
>
>
>
>
|
<
|
>
>
>
>
>
>
>
|
>
>
>
>

>
>
|
>
>
|
>
>
|
>
>
>
|
>
>
>
>
|
>
>
>
>
>
>
|
>
>
>
>
>
|
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>

|
>
>
|
>
>
>
>
>
|
>
>
>
>
>
>
>
>
|
>
>
>
>
>
>
>
|
>
>

>
>
>
>
|
<
>
>
|
<
<
<
>
>
>
>
>
>
>

|
>
>
>
>
>
|
>
>
>
>
>

>
|
>
|
<
>
>
|
|
>
>
|
>
>
>
>
>
>
>
|
>
>
>
|
<
>
>
>
>
>

>
>
>
>
>
>
|
>
>
>
|
>
>

>
>
|
>
>
|
>
>
>
>
|
>
>
|
>
>
|
>
>
|
>
>
>
|
>
>
>
|
>
>
>
>
>

>
>
>
>
|
>
>
>
>
|
>
>
>
>

>
>
>
|
>
>
>
|
>
>
>
>
|
<
>
|
|
>
>
|
>
>
|
>
>
>
|
>
>
>
>

>
>
|
>
>
|
>
>
|
>
>
|
>
|
>
>
|
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

>
>
|
>
>
>
>
|
>
>
>
>
|
>
>
|
>
>
>
|
>
>
>
>
>
>
>
>
|
>
>
>
>
|
>
>
>
>
|
>
>
>
>
>
|
>
>

<
<
|
>
>
|
>
>
|
>
>
|
>
>
>
>
|
>
>

>
|
>
>
>
>
|
>
>
>
>
|
>
>
>
>
|
>
>
|
|
>
|
>
>
>

>
>
|
>
>
|
>
>
|
>
|
>
>
|
>
>
>
|
>
|
|
>
|
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
|
|
>
|
>
>
>
>
>
|
>
|
>
|
>
|
>
>
>
|
>
>
|
>
>
>
|
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
>
>
|
>
>
|
>
>
|
>
>
|
|
>
|
>
>
|
>
>
|
>
>
>
|
>
|
>
>
>
|
>
>
|
>
>
|
>
>
>
>
>
>
|
>
>
>
|
>
>
>
>
|
>
>
|
>
>
>
>
|
>
>
|
>
>
|
>
>
>
|
>
>
>
|
>
>
>
>
>
>
|
|
>
|
>
>
>
>
>
|
>
>
>
>
|
|
>
|
>
>
>
|
>
|
>
>
|
>
|
>
|
>
|
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

>
>
>
|
>
|
>
>

>
>
|
|
>
|
>
>

>
>
|
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

|
>
|
>
>
>
>
|
>
>
|
>
>
|
>
>

>
|
>
>
|
>
>
>
|
>
|
>
>
|
>
>
|
>
>
>
>
|
>
|
>
|
<
>
>
>
>
|
>
|
>
|
>
|
|
>
|
>
>
|
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

>
|
>
>
|
|
>
|
>
>
>
|
>
>
>
>
|
>
>
>
|
>
>
>
|
>
>
|
>
>
|
>
>
>
|
>
>
>
>
>
>
>
>
>
|
|
>
|
>
>
>
>
|
>
>
>
>
>
>
>
|
>
>
>
>
>
>
|
>

>
>
>
|
|
>
|
>
>
|
>
>
>
>
|
>
|
>
>
>
>
>

|
>

>
>
|
>
>
>
|

>
|
>
>
|
>
>

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

>
>
|
>
|
>
>
>
|
>
>
|
|
>

>
>
|
>
|
>
>
|
>
|
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

>
>
|
|
>
|
>
>
|
>
>
>
>
>
>
|
>
>
>
>
>
>
>

|
>
|
>
>
|
>
>
>
|
>
|
|
>
|
>
>
>
>
|
>
>

>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
|
>
|
>
>
>
>
>
>

>
|
<
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

<
<
<
<
>

<
<
<
<
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
|
|
|
|
|
|
|
|
>
>
>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>

>

<
>
>
>
>
>
>
>
>
>
>
>
|
<
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

>
|
>
>
>
>
>
>
|
>
|
>
>
>
>
>
>
>
>
>
|
>
|
<
>
>
>
>
>
>
>
>
>
>
>

<
<
<
<
<
|
|
>
>
>
>
>
>
>
>
>
>
>
>
|
>
|
>
>
>
>
>
>
>
|
>
>
|
>
>
|
|
>

>
>
|
>
|
>
>
>
>

>
|
>
>
>
>
>
|
>
|
>
>
|
>
>
>
>
|
|
>

>
>
>
|
<
<
>
>
>
>
>
>
>
>
>
>
>
|
>
|
>
|
>
>
>
>
>
>
>

>
|
<
>
>
>
|
<
|
>
|
>

>
>
>
>
>
>
|
>

>
>
>
>
>
>
>
>
>
>
>
|
>

>
>
>
>
>
>
>
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
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
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93

94
95
96


97
98
99
100
101
102
103
104
105
106
107
108
109


110
111
112
113
114
115

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
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
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
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
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
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
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
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398

399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425

426
427
428
429
430
431
432
433
434
435
436
437
438
439
440

441
442
443
444
445
446

447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741





742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782

783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830


831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
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
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954

955
956


957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022

1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
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
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492

1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
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
1694
1695
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
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767

1768
1769
1770



1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795

1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814

1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
1883
1884
1885
1886
1887
1888
1889
1890
1891
1892
1893
1894
1895
1896

1897
1898
1899
1900
1901
1902
1903
1904
1905
1906
1907
1908
1909
1910
1911
1912
1913
1914
1915
1916
1917
1918
1919
1920
1921
1922
1923
1924
1925
1926
1927
1928
1929
1930
1931
1932
1933
1934
1935
1936
1937
1938
1939
1940
1941
1942
1943
1944
1945
1946
1947
1948
1949
1950
1951
1952
1953
1954
1955
1956
1957
1958
1959
1960
1961
1962
1963
1964
1965
1966
1967
1968
1969
1970
1971
1972
1973
1974
1975
1976
1977
1978
1979
1980
1981
1982
1983
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993
1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009


2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
2027
2028
2029
2030
2031
2032
2033
2034
2035
2036
2037
2038
2039
2040
2041
2042
2043
2044
2045
2046
2047
2048
2049
2050
2051
2052
2053
2054
2055
2056
2057
2058
2059
2060
2061
2062
2063
2064
2065
2066
2067
2068
2069
2070
2071
2072
2073
2074
2075
2076
2077
2078
2079
2080
2081
2082
2083
2084
2085
2086
2087
2088
2089
2090
2091
2092
2093
2094
2095
2096
2097
2098
2099
2100
2101
2102
2103
2104
2105
2106
2107
2108
2109
2110
2111
2112
2113
2114
2115
2116
2117
2118
2119
2120
2121
2122
2123
2124
2125
2126
2127
2128
2129
2130
2131
2132
2133
2134
2135
2136
2137
2138
2139
2140
2141
2142
2143
2144
2145
2146
2147
2148
2149
2150
2151
2152
2153
2154
2155
2156
2157
2158
2159
2160
2161
2162
2163
2164
2165
2166
2167
2168
2169
2170
2171
2172
2173
2174
2175
2176
2177
2178
2179
2180
2181
2182
2183
2184
2185
2186
2187
2188
2189
2190
2191
2192
2193
2194
2195
2196
2197
2198
2199
2200
2201
2202
2203
2204
2205
2206
2207
2208
2209
2210
2211
2212
2213
2214
2215
2216
2217
2218
2219
2220
2221
2222
2223
2224
2225
2226
2227
2228
2229
2230
2231
2232
2233
2234
2235
2236
2237
2238
2239
2240
2241
2242
2243
2244
2245
2246
2247
2248
2249
2250
2251
2252
2253
2254
2255
2256
2257
2258
2259
2260
2261
2262
2263
2264
2265
2266
2267
2268
2269
2270
2271
2272
2273
2274
2275
2276
2277
2278
2279
2280
2281
2282
2283
2284
2285
2286
2287
2288
2289
2290
2291
2292
2293
2294
2295
2296
2297
2298
2299
2300
2301
2302
2303
2304
2305
2306
2307
2308
2309
2310
2311
2312
2313
2314
2315
2316
2317
2318
2319
2320
2321
2322
2323
2324
2325
2326
2327
2328
2329
2330
2331
2332
2333
2334
2335
2336
2337
2338
2339
2340
2341
2342
2343
2344
2345
2346
2347
2348
2349
2350
2351
2352
2353
2354
2355
2356
2357
2358
2359
2360
2361
2362
2363
2364
2365
2366
2367
2368
2369
2370
2371
2372
2373
2374
2375
2376
2377
2378

2379
2380
2381
2382
2383
2384
2385
2386
2387
2388
2389
2390
2391
2392
2393
2394
2395
2396
2397
2398
2399
2400
2401
2402
2403
2404
2405
2406
2407
2408
2409
2410
2411
2412
2413
2414
2415
2416
2417
2418
2419
2420
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
2475
2476
2477
2478
2479
2480
2481
2482
2483
2484
2485
2486
2487
2488
2489
2490
2491
2492
2493
2494
2495
2496
2497
2498
2499
2500
2501
2502
2503
2504
2505
2506
2507
2508
2509
2510
2511
2512
2513
2514
2515
2516
2517
2518
2519
2520
2521
2522
2523
2524
2525
2526
2527
2528
2529
2530
2531
2532
2533
2534
2535
2536
2537
2538
2539
2540
2541
2542
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
2587
2588
2589
2590
2591
2592
2593
2594
2595
2596
2597
2598
2599
2600
2601
2602
2603
2604
2605
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
2657
2658
2659
2660
2661
2662
2663
2664
2665
2666
2667
2668
2669
2670
2671
2672
2673
2674
2675
2676
2677
2678
2679
2680
2681
2682
2683
2684
2685
2686
2687
2688
2689
2690
2691
2692
2693
2694
2695
2696
2697
2698
2699
2700

2701
2702
2703
2704
2705
2706
2707
2708
2709
2710
2711
2712
2713
2714
2715
2716
2717
2718
2719
2720
2721
2722
2723
2724
2725
2726
2727
2728
2729
2730
2731
2732
2733




2734
2735




2736
2737
2738
2739
2740
2741
2742
2743
2744
2745
2746
2747
2748
2749
2750
2751
2752
2753
2754
2755
2756
2757
2758
2759
2760
2761
2762
2763
2764
2765
2766
2767
2768
2769
2770
2771
2772
2773
2774
2775
2776
2777
2778
2779
2780
2781
2782
2783
2784
2785
2786

2787
2788
2789
2790
2791
2792
2793
2794
2795
2796
2797
2798

2799
2800
2801
2802
2803
2804
2805
2806
2807
2808
2809
2810
2811
2812
2813
2814
2815
2816
2817
2818
2819
2820
2821
2822
2823
2824
2825
2826
2827
2828
2829
2830
2831
2832
2833
2834
2835
2836
2837
2838
2839
2840

2841
2842
2843
2844
2845
2846
2847
2848
2849
2850
2851
2852





2853
2854
2855
2856
2857
2858
2859
2860
2861
2862
2863
2864
2865
2866
2867
2868
2869
2870
2871
2872
2873
2874
2875
2876
2877
2878
2879
2880
2881
2882
2883
2884
2885
2886
2887
2888
2889
2890
2891
2892
2893
2894
2895
2896
2897
2898
2899
2900
2901
2902
2903
2904
2905
2906
2907
2908
2909
2910
2911
2912
2913
2914
2915
2916
2917
2918
2919
2920
2921


2922
2923
2924
2925
2926
2927
2928
2929
2930
2931
2932
2933
2934
2935
2936
2937
2938
2939
2940
2941
2942
2943
2944
2945
2946
2947

2948
2949
2950
2951

2952
2953
2954
2955
2956
2957
2958
2959
2960
2961
2962
2963
2964
2965
2966
2967
2968
2969
2970
2971
2972
2973
2974
2975
2976
2977
2978
2979
2980
2981
2982
2983
2984
2985
2986
2987
3.1.0, 2010.06.03 (r2670)

    o Default MySQL version now 5.1, having entered GA since 3.0.9.

    o Lots of platform updates tracked, lots of warnings from newer
      compilers squished.  Most by me, some by Adrian Cornish.

    o Added Query::insertfrom(), plus associated classes SQLStream,
      NoTransactions, and the InsertPolicy hierarchy.  Also adds
      examples/ssqls6.cpp, which shows how to use this new feature.
      Thanks for this feature go to Rick Gutleber, except for
      RowCountInsertPolicy, by me.

    o Added comparison operators to tiny_int<T>.  Thanks for this patch
      go to Edward Diener.

    o Added SQLTypeAdapter::is_null().  This lets you retrieve a
      nullable column from the DB, then re-insert a value from that
      column back into the DB via a template query without explicit
      checks for null-ness; it will do the right thing now.

    o Added -f flags to lib/*.pl header file generating scripts to
      allow overriding the default limit of 25 fields for tqueries
      and SSQLSes without having to edit the file, as in previous
      versions of MySQL++.  Also added --with-field-limit option to
      the configure script so you can give both -f options at once
      during the build process.  This latter is especially useful
      for automated binary package builders.

    o The file lib/querydef.h (generated by lib/querydef.pl) now
      defines the MYSQLPP_TQUERY_MAX_PARAMETERS macro, giving the
      maximum number of parameters the functions in the generated file
      allow for template queries.  Similarly, lib/ssqls.h (generated
      by lib/ssqls.pl) defines MYSQLPP_SSQLS_MAX_MEMBERS.

    o Added ConnectionPool::safe_grab(), which pings the grabbed
      connection before returning it.  If the ping fails, we remove
      the dead connection from the pool and try again.  This doesn't
      eliminate the possibility of returning a dead connection;
      there is no protection against race conditions.  It is merely
      a best-effort attempt.

    o Added ConnectionPool::remove(Connection*), which removes a
      connection from the pool.

    o Added ConnectionPool::exchange(), which wraps remove()
      and grab().

    o Added a feature to Transaction, where it can send a SET
      TRANSACTION ISOLATION LEVEL query before it starts the
      transaction proper, affecting the isolation level and the scope
      of that change.

    o Added ScopedConnection class.  Initial version by Joel Fielder,
      lots of changes by me.  Using it instead of explicit safe_grab()
      and release() calls on the pool in examples/cpool.cpp.

    o Added FieldNames::operator[](size_type) overloads.  This is
      necessary to correctly overload the base class versions inherited
      from std::vector.

    o FieldNames wasn't doing field-by-name matches case insentitively,
      most likely since 3.0.0 when we changed it to derive from
      std::vector.  This caused SSQLS (at least) to be case sensitive.
      Fixed this and renamed the stock.sdate field in the SSQLS
      examples to stock.sDate to test this.

    o Added Query::replace(iter, iter), on the model of existing
      insert(iter, iter).  Thanks for this patch go to David Walthour.

    o Added Query::operator!(), overriding basic_ios version so that
      "if (!query)" does the right thing.  Fixes problem report in
      thread http://lists.mysql.com/plusplus/8594

    o Query copy ctor and assignment operator now perform deeper
      copies, so you can pass Query objects around in certain ways
      that used to cause crashes.  Thanks for this patch go to Steven
      Van Ingelgem.

    o Defined *_null variants for every sql_* typedef, wrapping
      all those earlier types in Null<>.  All example programs now use
      these types instead of explicit Null<>-wrapped types.

    o Created a C++ command line parsing mechanism for the examples
      today, and for programs coming in the future.  It uses the
      platform version of getopt() if available, substituting a
      public-domain implementation that gets built into MySQL++
      itself otherwise.  It's documented in the refman -- see
      the CommandLineBase class -- but it's in the newly created
      mysqlpp::internal namespace, which means we don't promise any
      sort of ABI or API stability for it.  You're welcome to use it
      in your own programs, but expect it to change without warning.


    o Added a few missing MYSQLPP_EXPORTs to operator<<()s for stream
      manipulators, to allow their use when MySQL++ is built as a DLL.



    o Added backticks around table and column identifiers in all
      code paths exercised by dtest.  There are some others remaining,
      particularly things like Row::field_list().  Thanks for this
      patch go to Adrian Cornish.

    o Added mysqlpp::NOW() which returns a value that, when inserted
      into a SQL query, results in a call to SQL's NOW() function.
      DateTime::now() -- added in 3.0.0 -- does the same thing,
      but this is shorter and matches the SQL syntax.

    o Calling DBDriver::disconnect() twice no longer calls
      mysql_close() twice.



    o Worked around a weakness on Windows that caused problems in code
      with a connect(), disconnect(), connect() call pattern, when
      also using a named pipe to connect to the DB.  (There never
      has been a problem with this on other platforms or with other
      IPC mechanisms.)


    o Initializing a SQLTypeAdapter with a floating-point value
      equal to infinity or NaN results in SQL null if the type
      is also nullable, or 0 otherwise.  Previously, we got an
      implementation-defined string, which could give invalid SQL,
      or could give 0, a different value from NaN, infinity, or
      SQL null.  This does collapse the notions of NaN and infinity,
      but the MySQL reference manual doesn't say how you're supposed
      to preserve these differences.

    o Removed the dependency of stadapter.h on sql_types.h, just to get
      sql_tinyint*.  #including tinyint.h instead, and using equivalent
      types to what sql_types.h defines.  This is necessary because
      sql_types.h should be one of the last things included from
      mysql++.h, so that it can define sql_* equivalents for everything
      else in MySQL++, which means all those other things need to be
      #included by that point.

    o The "find MySQL++" autoconf macro (config/mysql++.m4) now
      searches for the library in lib64 subdirectories everywhere it
      also looks in lib.  We did this for the C API finder macro way
      back in MySQL++ 2.2.0, and only neglected to do it for this
      macro because it's not used by MySQL++ itself, just provided
      as a courtesy to MySQL++ users that also use autoconf.

    o Also improved the "find C API" macro (config/mysql_loc.m4)
      so it, too, is more useful in third-party projects.

    o Moved private FieldNames::str_to_lwr() method out into its
      own module, in the new mysqlpp::internal namespace, so other
      modules can use it.  Also added an overload for this new global
      method taking std::string instead of char*.

    o userman build process can now find FOP when installed from
      the standard Ubuntu/Debian package repository.

    o No longer generating refman.pdf.  It's difficult to generate
      properly on some platforms, and isn't all that useful anyway
      compared to the HTML version, which builds properly everywhere.

    o Dropped custom.h backwards-compatibility header.  (Deprecated
      over a year ago in MySQL++ 3.0.0.)

    o Fixed a bad pointer access crash in Connection::set_option()
      triggered when the option set call fails.  Thanks for this
      patch go to Kevin Regan.

    o ReconnectOption behavior now knows about a fix in MySQL 5.1.6 and
      newer that lets you set it either before the connection is up,
      or after.  If you try to set this option when MySQL++ is built
      against earlier versions of the MySQL C API, it will refuse to
      set the option because it knows the option will be reset when
      the connection comes up.

    o No longer trying to make the C API library read from a "my"
      options file before connect.  It does that by default, and
      the file is supposed to be .my.cnf anyway.

    o Reworked the load_jpeg example code for clarity, extracting
      load_jpeg_file() routine as an implementation detail and
      making that use the C++ stringstream "slurp into string" idiom
      instead of allocating a C char buffer and copying that into
      a std::string.

    o Restored support for repeating query parameters.  Apparently
      you could say things like "stuff %0 morestuff %0" in v2.1,
      but this was broken by initial 1-parameter fixes in v2.2.
      This patch reportedly lets us have both things at once, and
      improves handling of 1-parameter template queries in general.
      Thanks for this patch go to Martin Gallwey.

    o Added examples/tquery4.cpp based on test code and feedback
      from Martin.

    o Put Comparable class in namespace mysqlpp, where it should always
      have been.  Aside from being just plain wrong, it caused a
      conflict with Boost if you used its Comparable class and hoist
      them both into the global namespace.  Thanks for this patch go
      to Michael Radzewitz.

    o Fixed all the known problems with the Xcode project files.

    o Skeletal support for SSQLS v2.  Doesn't do anything useful
      yet, it just got caught up in the need to release 3.1 as-is.

    o Various enhancements to the test suite.

    o Many, many documentation enhancements.


3.0.9, 2009.02.04 (r2442)

    o It is now possible to use Null<T> objects in const context.

    o Query was emitting thousands separators when used in some
      locales.  Thanks for the fix go to Tomaž Šolc.

    o Restored support for using Query::storein() with template
      queries.  Was mistakenly removed in the 3.0.0 development
      process.

    o GCC 4.4 build fixes.  Thanks for this go to Remi Collet.


3.0.8, 2008.11.27 (r2432) The "Thanksgiving" release

    o Fixed a VC++ build error introduced in 3.0.7 in the Sun CC fix.

    o Fixed the Makefile we generate from Makefile.simple for the
      devel RPM.  The recent Bakefile upgrade changed the output so
      our munger stopped munging.

    o Changed all instances of "CREDITS" in header comments to
      "CREDITS.txt".

    o Brought ebuild file up to date with what Gentoo has been
      using for 2.3.2.


3.0.7, 2008.11.21 (r2423)

    o Fixed bug where initting a Query with a query string and then
      appending more to it with operator <<() would start overwriting
      the beginning of the buffer.  Thanks for the fix go to Chris
      Frey.

    o Added String::empty(), to parallel std::string better.

    o Added SQLTypeAdapter ctor for Null<String>, to allow SSQLS with
      NULL BLOB columns.  Thanks for this patch go to Russell Robinson.

    o Passing on "throw exceptions" flag in Query::storein() to the
      temporary Row objects it creates.  (Should have done this
      all along.)

    o All MySQL++ classes with operator[]() and at() methods now
      throw the new BadIndex exception on out of range indices now,
      unconditionally.  Before, it was a mishmash of MySQL++-specific
      mechanisms, std::range_error, and unchecked access.

    o Fixed some bugs in load_jpeg and cgi_jpeg examples that prevented
      them from working correctly on Windows.

    o Squished some warnings and incompatibilities that caused
      difficulty with Solaris CC.

    o Several minor fixes to allow building on Cygwin again.

    o Dedicated VC++ 2008 support.  (Not just a clone of VC++ 2005
      project files in a different directory.)

    o Lots of documentation improvements.


3.0.6, 2008.08.16 (r2350)

    o Several fixes to allow thread-aware build on Solaris

    o More improvements to search for Fink version of C API library.

    o Various improvements to Windows installer (install.hta)


3.0.5, 2008.08.06 (r2332)

    o Replaced install.bat with new install.hta, which has a GUI and a
      lot of embeded logic for doing The Right Thing, which we couldn't
      do in a dumb batch file.

    o Several fixes to allow it to build on Solaris 10.

    o Fixed a bug in comparison of Null<T> to T: wouldn't always give
      the right result for one particular combination of argument
      values and order of parameters to operator <().  It wouldn't
      fail all the time, either; it depended on the way the system's
      memory allocator dealt with newly allocated RAM.  The bug was
      discovered during the Solaris 10 porting effort, but it is not
      a Solaris-specific bug.

    o Split Linux-specific material out of README-Unix.txt into
      README-Linux.txt, and created README-Solaris.txt.

    o Shipping a vc2008 directory.  Populated by bootstrap script with
      copies of vc2005 files when those are newer, with the idea being
      to update them by hand by running them through VC++2008 before
      release.

    o Several fixes to VS-only examples. They hadn't been updated to
      track several of the changes in MySQL++ v3, so they wouldn't
      build OOTB at all, crashed when you did get them building, and
      emitted a lot of warnings during the build.  Cleaned it all up.

    o Autoconf now explicitly checks whether we need to link to zlib
      to link to MySQL C API library.  It used to be required, but
      lately, MySQL has been shipping the library with zlib stuff
      embedded, causing multiply defined symbol errors on some systems.

    o configure script now looks in more locations for the MySQL C API
      library, adding default locations for Fink and Solaris.


3.0.4, 2008.07.02 (r2303)


    o Fixed a few bugs in SslOption that prevented it from actually
      working.  If you've been having SSL problems since upgrading
      to MySQL++ v3, this is why!  Thanks for these patches go to
      Petteri Kiiskinen.

    o Changed type of String's internal "size" typedefs so it'll
      build without errors on 64-bit systems where these ints are
      different sizes.

    o Many user manual improvements.


3.0.3, 2008.05.11 (r2284)

    o Fixed query well-formedness handling in Query::store() and use().
      It was quietly eating these errors, confusing them with the
      no-results case.

    o Fixed examples/cpool.cpp to build without thread support.

    o No longer hiding all stdint.h typedefs inside namespace mysqlpp.

    o Fixed mysqlpp::String comparisons of empty strings against
      nonempty strings; if the empty string was on the left hand side,
      it would succeed because it was only comparing against characters
      in the empty side, which matches everything.  (Fixes bug 11588.)


3.0.2, 2008.04.13 (r2275)

    o Increased float to string conversion precision from 7 to 9 and
      double from 16 to 17 digits.  Previous values weren't enough
      near the maximum values that each can hold.

    o Replaced Query's safe bool mechanism with an override of
      basic_ios::operator void*() to avoid a conflict between the
      two mechanisms.  As the base class version isn't virtual,
      this is arguably evil, but it should be harmless in typical use.
      Besides, testing Query in bool context usually isn't the right
      thing anyway: test the result set instead.

    o Made ConnectionPool::grab() virtual.

    o Overriding ConnectionPool::grab() and release() in
      examples/cpool.cpp to show how to do connection-in-use count
      limiting.  Also, added a few more output indicator states to
      allow one to better understand program flow.


3.0.1, 2008.03.23 (r2263)

    o String objects can now be compared to mysqlpp::null directly.

    o Added a template operator== and operator!= to String, syntactic
      sugar for the existing String::compare() methods.

    o String::compare() now returns 0 ("equal") when one of the
      strings is an uninitialized String() (no refcounted buffer)
      and the other is empty.  It used to consider any initialized
      string greater than an uninitted one.  An uninitialized String
      appears empty, though, so this was incorrect.

    o Made Connection::thread_aware(), thread_start() and thread_end()
      static methods, so they can be called before you create your
      first connection.  Ditto for DBDriver versions of these methods.

    o Calling Connection::thread_start() and thread_end() in
      examples/cpool.cpp, as appropriate.  Above changes were necessary
      to make this work sensibly.

    o Made ConnectionPool::release() virtual, so your pool subclass can
      override it.

    o Added ConnectionPool::size(), so a subclass can know the current
      number of extant connections.

    o No longer single-quoting NOW() call generated for default
      init of DateTime type when building queries from SSQLS objects
      in Query::insert(), replace() and update().  The template query
      and stream interfaces of Query treated NOW() correctly already.


    o Fixed a bug that left SSQLS::table_override_ uninitted if
      you used certain of the generated ctors or set() member
      functions instead of others used by the examples.  This could
      cause a crash any time you caused SSQLS.table() to be called,
      such as when passing the SSQLS to Query::insert().

    o Minor memset bug fixed in test/uds.cpp.  Patch by Dave Jones.


3.0.0, 2008.02.29 (r2236) The "Giant Leap Forward" release

    THIS IS NOT A DROP-IN REPLACEMENT FOR MySQL++ v2.x!

    You will have to recompile your program against this version
    of the library, and you will almost certainly have to make code
    changes as well.  Please see these sections in the user manual
    for information on migrating your code to this new version:

    http://tangentsoft.net/mysql++/doc/html/userman/breakages.html#api-3.0.0
    http://tangentsoft.net/mysql++/doc/html/userman/breakages.html#abi-3.0.0

    o Added ConnectionPool class, primarily to let multithreaded
      programs share a set of Connection objects safely in situations
      where it isn't acceptable to have a Connection per thread.

    o Created examples/cpool.cpp to demonstrate this new class.


    o Added RefCountedPointer template, which provides automatic
      memory management and data sharing.  It's not intended
      for use outside of MySQL++ itself, but it's the mechanism
      behind everything below where reference counting is mentioned.
      I created the initial version of it, but Jonathan Wakely almost
      completely rebuilt it, and Joseph Artsimovich provided helpful
      commentary and advice as well.

    o Many improvements to Specialized SQL Structures (SSQLS):

      - Renamed custom* to ssqls*.  There's still a custom.h which
        #includes ssqls.h for you, but it's only intended to ease
        the transition to the new name.  It will go away in a future
        release, probably as soon as v3.1.


      - SSQLSes are finally compatible with Null<>-wrapped types.  This
        feature is based loosely on the "Waba" patch posted to the
        mailing list back in the v2.0 days, but extended to allow
        Null<T> types for key fields.  (The Waba patch only allowed
        these types in non-key fields.)


      - It's no longer necessary to define a different SSQLS for each
        different field set you use in queries.  That is to say,
        you can define an SSQLS for an entire table and store just a
        subset of the table in it now, with the other fields keeping
        default values.  Removed examples/custom6.cpp, as custom1.cpp
        can now demonstrate the same thing, implicitly.

      - An SSQLS's field order no longer has to match the order of
        fields in the result set it is populated from.

      - As a result of previous, removed sql_create_c_order_* macros;
        they have no purpose now.

      - Removed order parameters from sql_create_complete_*, which now
        gives it the same functionality as sql_create_c_names_* so
        removed the latter, too.

      - Removed "basic" variants of SSQLS creation macros.  They've
        been unofficially deprecated by dint of being all but
        undocumented and unexemplified for a very long time now.

      - It's now possible to use mysqlpp::String, Date, DateTime, and
        Time types in the key field positions in an SSQLS as they
        now support the necessary comparison interfaces.

      - If you use a floating-point data type in one of the key field
        positions, it no longer uses exact comparison logic.  Instead,
        it now does [in]equality comparisons by testing whether the
        difference between two floating-point values is less than a
        configurable threshold defaulting to 0.00001.
    
      - You can now use 'bool' type in an SSQLS.

      - Renamed _table static member variable in each SSQLS to table_
        and made it private.  There are now public setter and getter
        methods, table().

      - Added per-instance table name overriding via instance_table()
        setter.  table() getter returns static version if this is not
        set, so it's still a global setting by default.

    o You can now use mysqlpp::null as a template query parameter to
      get a SQL null.

    o Replaced template ColData_Tmpl<T>:

      - Used to have typedef ColData_Tmpl<std::string> MutableColData.
        It was used only once within MySQL++ itself, and was never
        documented as a class for end users.  This one use within
        the library was a crock, so we just replaced this use with
        std::string and removed the typedef.

      - This left just one use of ColData_Tmpl<T>, instantiating it
        with the MySQL++ utility class const_string, basically a
        clone of std::string with all the mutating features removed.
        Folded the functionality of const_string into the template,
        renamed the result to String, and deleted the const_string
        class.  It'd be a complete std::string replacement -- with
        SQL-related enhancements -- if it were modifiable, but MySQL++
        doesn't need it to be modifiable.  Yet, it's still the closest
        thing MySQL++ has to its own string type; thus the name.

      - Replaced its internal buffer management with a much more
        clever reference counted scheme.  This shows its greatest
        advantage in the return from Row::operator[](), which for
        technical reasons must return by value, not by reference
        as is more common.  This lets you pass around Strings by
        value while having the efficiency of reference semantics.
        This can be important with large return values, like BLOBs.

      - Converting String to numeric types (ints, floats...) uses a
        new, cleaner system by Jonathan Wakely.  Unless you were
        abusing weaknesses in the old system, you won't see a
        difference.  It's just more robust and flexible.

    o Redesigned SQLString:

      - It used to derive from std::string, and while MySQL++'s
        internals did use it in place of std::string, these places
        didn't take advantage of the additional features offered
        by SQLString.  So, replaced all those uses with std::string.

      - All the remaining uses are MySQL++ public interfaces that
        need to be able to accept any of many different data types,
        and we want that data to be automatically converted to a
        SQL-compatible string form.  Because it no longer has the
        parentage to be a general-purpose string type and MySQL++ has
        a new contender for that role (String), renamed SQLString to
        SQLTypeAdapter to reflect its new, limited purpose.  ("STA"
        for short.)

      - Since we don't have the std::string base class to manage the
        string buffer any more, using the same reference counted
        buffer mechanism as String.  In addition to saving code by
        not creating yet another buffer management mechanism, it means
        objects of the two classes can share a buffer when you assign
        one to the other or pass one to the other's copy ctor.

      - Added many more conversion ctors.

      - STA interfaces using the 'char' data type now treat them as
        single-character strings instead of one-byte integers, as
        does the Standard C++ Library.

      - Added mysqlpp::tiny_int interfaces to STA to replace the
        former char interfaces for those needing one-byte integers.

    o As a result of the ColData -> String redesign, removed
      Row::raw_*().  Before String copies were efficient, this
      was helpful in accessing BLOB data efficiently.  It was also
      required back when ColData didn't deal correctly with embedded
      null characters, but that reason is gone now, too.

    o Row::operator[](const char*) no longer unconditionally throws the
      BadFieldName exception when you ask for a field that doesn't
      exist.  It will still throw it if exceptions are enabled, but if
      not, it'll just return an empty String.  This was necessary to
      make the SSQLS subset and field order independence features work.

    o Similarly, Result::field_num() returns -1 when exceptions are
      disabled and you ask for a field that doesn't exist.

    o You can now use the OptionalExceptions mechanism to disable
      exceptions on const MySQL++ objects.

    o Redesigned query result classes:

      - Instead of Result deriving from ResUse, the two derive from
        a common base class -- ResultBase -- containing the bits that
        are truly the same between them.  Before, Result inherited
        several methods that didn't really make sense for "store"
        query result sets.

      - Renamed Result to StoreQueryResult and ResUse to UseQueryResult
        so it's clearer what each is for.

      - Renamed ResNSel to SimpleResult.

      - Made all SimpleResult data members private and hid them behind
        const accessor functions of the same name.

      - The result set classes all used to be friends of Connection
        for various lame reasons.  Since they are created by Query,
        and Query has a good reason for a strong relationship with
        Connection, moved Connection access out of each result set
        class into the code in Query that creates that type of result
        set object.

      - StoreQueryResult now derives from vector<Row> in addition to
        ResultBase; it used to merely emulate a vector of Rows, poorly.
        It can now dispose of the MYSQL_RESULT at the end of object
        construction, because it creates all the Row objects up front
        instead of on the fly.  And as a result of *that*, operator[]
        returns by reference instead of by value, operator -> works
        correctly on iterators, all STL algorithms work, etc., etc.

      - IMPORTANT COMPATIBILITY BREAK: because we used fetch_row()
        stuff in Result previously, it was okay to index past the
        end of the result set: you'd just get a falsy Row when you
        did this, just as happens when doing the same thing in a
        "use" query.  The simple1 and simple2 examples did this,
        so it's likely that code exists that takes advantage of this
        misfeature.  New versions of these examples show how to index
        through a StoreQueryResult without running past its end.

      - ResUse used to delay creation of its FieldNames and FieldTypes
        objects until the point of need.  This had several implications
        for thread and exception safety that we fix by just creating
        them in the ctor.  If your code is multi-threaded and was
        avoiding certain usage patterns due to crashes, it's worth
        trying your preferred way again.

      - Result sets create a few data structures to hold information
        common to all rows in that set.  The row objects need access
        to these shared data structures, so on creation each gets
        a pointer back to the result set object that creates it.
        This was efficient, but required that a result set object
        outlive any row objects it creates.  Now these shared data
        structures are reference-counted, decoupling the lifetime of
        the child row objects from their result set parent.

      - Copy operations for result sets used to actually be "moves"
        before, for efficiency.  (MySQL++ itelf only copied result
        sets in returning them by value from the query execution
        methods of Query, so this was acceptable if you didn't do
        anything uncommon with these objects.)  Reference counted
        data structures allow us to have copy semantics now without
        sacrificing efficiency.

      - You can now use Query::storein() with an STL container of Row
        objects now, instead of having to use SSQLSes.  The lifetime
        issue guaranteed a crash if you tried this before.

      - Removed a bunch of unnecessary alias methods:

        - columns() -> num_fields()
        - names()   -> field_names()
        - rows()    -> num_rows()
        - types()   -> field_types()

      - Renamed several methods for grammar reasons:

        - fields(unsigned int)      -> field(unsigned int)
        - names(const std::string&) -> field_num(const std::string&)
        - names(int)                -> field_name(int)
        - types(int)                -> field_type(int)

      - Removed several "smelly" methods:

        - purge()
        - raw_result()
        - reset_names()
        - reset_field_names()
        - reset_types()
        - reset_field_types()

    o Field class used to just be a typedef for the corresponding C
      API class.  Now it's a real C++ class providing a more MySQL++
      sort of interface, plus good OO things like information hiding
      and implementation detail abstraction.  This changes several
      things about the interface.

    o Fields class was basically a specialized std::vector work-alike
      for dealing with the C API to get access to MYSQL_FIELD objects
      and present them as contained Field objects.  New Field type
      let us replace it with "typedef std::vector<Field> Fields"

    o Major improvements to the quoting and escaping mechanisms:

      - Replaced almost all of the type-specific interfaces in manip.h
        with a single version taking STA.  The compiler can convert
        almost anything to STA without losing any information we need
        for correct quoting and escaping.  This has the side benefit
        that we can now do correct quoting and escaping for more data
        types now, including plain C and C++ string types.

      - Fixed a bug in quote_double_only manipulator for String: was
        using single quotes by mistake.

      - Escaping and quoting only works in instances where MySQL++
        can tell you're building a SQL query and are using a data type
        that requires it.  This affects many things, but the one most
        likely to cause trouble is that inserting MySQL++'s quoting
        and escaping manipulators in non-Query ostreams is now a no-op.

      - Added escape_string() member functions to Query and
        SQLQueryParms::escape_string(), and removed the global function
        of the same name.  Because these are tied indirectly to a
        Connection object, this also has the effect that escaping is
        now aware of the current default character set used by the
        database server.  There's only one case where this isn't done
        now, and that's when we're disconnected from the server.

      - Previous two items form a trade-off: if your code was depending
        on MySQL++ to get SQL escaping and it no longer happens for
        what we consider a good reason, you can build a replacement
        mechanism using these new functions.  Quoting needs no special
        support in MySQL++.

      - Removed 'r' and 'R' template query parameter modifiers,
        which meant "always quote" and "always quote and escape"
        regardless of the data type of the parameter.  There are no
        corresponding manipulators (for good reason), so the removal
        restores symmetry.

    o Created DBDriver class from code previously in Connection and
      Query to almost completely wrap the low-level MySQL C API:

      - Connection creates a DBDriver object upon connection and
        passes a pointer to it down to Query objects it creates.
        In turn, they pass the pointer on to any of their children
        that need access to the C API.

      - Nothing outside DBDriver calls the C API directly now, though
        DBDriver leaks C API data structures quite a lot, so this
        feature doesn't constitute "database independence."  See the
        Wishlist for what must be done to get to that point.

    o Completely redesigned the connection option setting mechanism:

      - There's now just a single Connection::set_option() method that
        takes a pointer to the abstract Option base class, and there is
        an Option subclass for every connection option we understand.
        Thus, type errors are now caught at compile time instead of
        at run time.

      - Replaced Connection::enable_ssl() with SslOption class.

      - Enabling data compression and setting the connection timeout
        are no longer set via parameters to Connection interfaces.
        These are now set with CompressOption and ConnectTimeoutOption.

      - Similarly, removed client_flag parameters from Connection's
        ctor and connect() method and added corresponding Option
        subclasses.  There's about a dozen, so rather than list them





        here, look for similarly-named classes in lib/options.h.

    o Added Connection::count_rows() to execute "SELECT COUNT(*) FROM
      tablename" queries for you.

    o Moved Connection::affected_rows(), info() and insert_id() methods
      to class Query, as they relate to the most recently-executed
      query, not to the connection.

    o Several method name changes in Connection:

      - client_info()   -> client_version()
      - host_info()     -> ipc_info()
      - proto_info()    -> protocol_version()
      - server_info()   -> server_version()
      - stat()          -> status()

    o Removed Connection::api_version().  It does the same thing as
      client_version().

    o Lots of changes to Date, DateTime, and Time classes:

      - If you use the default constructor for DateTime and don't
        subsequently set its year, month, day, hour, minute or second
        data members to nonzero values, it becomes the SQL function
        "NOW()" in a query string.  You can also use DateTime::now()
        as syntactic sugar for this.

      - As a result of above, had to hide all of DateTime's data
        members behind accessor functions, to keep the state of the
        object consistent.  (If it's initialized as "now" and you
        give it an explicit year value, say, it is no longer "now",
        so the setter has to clear the now-flag.)  There are getters
        and setters for year, month, day, hour, minute and second,
        all named after the member.

      - Did the same for Date and Time for consistency, even though it
        isn't technically required.

      - The sql_timestamp typedef now aliases DateTime instead of Time.


      - Renamed template class DTbase<T> to Comparable<T>.  The fact
        that it's the common base class of all date and time classes
        is irrelevant; making subclasses comparable is what it does,
        so that's what it should be named after.

      - Added a DateTime ctor taking discrete year, month, day, hour,
        minute, and second values.

      - Implicit conversion from stringish types to the date and time
        types is no longer allowed.  This is part of the "Waba"
        Null<T> patch mentioned above; allowing implicit conversions
        would break this new feature.

      - Added operator std::string and str() methods to all of these
        classes.  Adding this to the existing operator << support, you
        now have several ways to convert these objects to string form.

      - Added time_t conversion to Date and Time classes.  DateTime
        already had it, since it's more legitimate to convert time_t
        to DateTime, but you could already "slice" it with something
        like Time(DateTime(time(0))) so there's no point pretending
        you can't get from time_t to Date or Time.  Might as well
        legitimize it.

    o Improved tiny_int class:
        
      - Turned it into a template parameterized on the value type so
        you can get both signed and unsigned TINYINTs

      - Changed the sql_tinyint and sql_tinyint_unsigned typedefs to
        use mysqlpp::tiny_int<VT> instead of raw chars

      - Added a bool conversion ctor and operator, and typedef'd it
        to sql_bool and sql_boolean to match MySQL server behavior

    o Added many more sql_* typedefs.  We now have a typedef for every
      type the MySQL server knows about, including those it supports
      just for compatibility with other database servers.

    o Changed the sql_*int* typedefs to use integer types of the same
      size as the MySQL server.  (Run test/inttypes.cpp to test it.)

    o Added copy ctor and assignment operator to Row.

    o Row::operator[]() takes int now instead of unsigned int.
      This finally (!) makes it possible to say row[0] without the
      compiler giving an ambiguous overload error.



    o Changed all uses of row.at(0) in the examples to row[0]

    o Added operator[] to all classes that only had at().

    o Query now automatically resets itself unless the query fails
      or you're using template queries.  In either case, the contents
      of the query's internal buffers are considered precious,
      either for debugging, or future queries.  Except when using
      template queries, this means you may be able to avoid calling
      Query::reset() entirely.  It's still safe to call reset()
      as before, just unnecessary most of the time.

    o Removed reset_query parameter from all Query methods.  It was
      almost completely broken before, and above change does what
      was really wanted to begin with.

    o Query::store_next() and Result::fetch_row() no longer throw
      the EndOfResults and EndOfResultSets exceptions; these are not
      exceptional conditions!  These methods simply return false now.

    o Removed examples/usequery.cpp: there's no essential difference
      between what it did and what examples/simple3.cpp does now as
      a result of the previous change.

    o Added Query::exec(void), paralleling Query::execute(void).

    o Removed Query::preview().  The most direct replacement is str(),
      which has always done the same thing.

    o You can now insert a Query object into an ostream to get a copy
      of the built query.  This means Query::str() is only necessary
      when using template queries.

    o Removed overloads of Query::execute(), store(), and use()
      that take const char*.  It was redundant because const char*
      converts implicitly to STA, for which overloads already exist.

    o Renamed Query::def to Query::template_defaults to make its
      purpose clearer.

    o Query::error() now returns const char*, not a std::string by
      value.  There's no point in making a copy of the error string.
      The method is now const as well, as it doesn't change the
      Query object.

    o Added Query::errnum(), which just wraps Connection::errnum().

    o Added error number parameters and accessor functions to BadQuery,
      ConnectionFailed and DBSelectionFailed exceptions, to preserve
      the state of Connection::errnum() at the point of the exception,
      so you don't have to rely on this value remaining unchanged
      during the exception throw process.  All places that use these
      exceptions now include this value where possible.  Thanks for the
      initial patch go to Jim Wallace.

    o Removed Lockable mechanism from Connection and Query; it was
      conceptually flawed.  See the new user manual chapter on
      threading for advice on using MySQL++ safely without locking.
      There is mutex locking now in ConnectionPool, but that's it.

    o Connection::query() now takes an optional query string, allowing
      the returned Query object to start off with a value.  Especially

      useful when the query string is static, either because it's
      a simple query or because it's a template.  You can now build
      chains like "if (conn.query("CREATE INDEX ...").exec()) { ..."

    o Added Connection::thread_aware(), thread_end(), thread_id()
      and thread_safe().  See user manual's threading chapter for
      explanations.

    o Renamed "success" data members in Connection, Query and
      SimpleResult (neé ResNSel) to "copacetic_", making them private
      if they weren't before.  This better reflects their actual
      use, which isn't to say that there has necessarily been actual
      success, but rather that everything's okay with the object.

    o Removed success() member functions from above classes.  All can
      be tested in bool context to get the same information.

    o Replaced all operator bool()s in MySQL++ classes with safer
      alternatives.  See http://www.artima.com/cppsource/safebool.html
      Thanks to Jonathan Wakely for much helpful commentary, advice,
      and code used in these mechanisms.

    o Decoupled Connection::copacetic_ from Connection::is_connected_.
      It is now possible for the object to be copacetic without being
      connected.  However, if it tries to connect and fails, then
      it is not copacetic.  If it is copacetic and not connected, it
      means we haven't even tried to connect yet, a useful distinction.

    o Collapsed Connection's host, port, and socket_name down into
      a new combined 'server' parameter which is parsed to determine
      what kind of connection you mean.  These interfaces are still
      compatible with v2.3 and earlier up through the port parameter.
      There are differences beyond this.

    o Added TCPConnection, UnixDomainSocketConnection and
      WindowsNamedPipeConnection subclasses for Connection giving
      simpler construction and connect() method interfaces for
      instances where you know what kind of connection you want at
      compile time.

    o Changed Connection::ping() return value from int to bool.

    o Renamed NullisNull to NullIsNull -- capital I -- and similar for
      NullisZero and NullisBlank.

    o It's now a compile-time error to try to convert a MySQL++
      representation of a SQL null to any other data type, rather
      than a run-time error as in previous versions.  Removed
      BadNullConversion exception as a result.

    o Way back in v1.7.x we used the BadQuery exception for all kinds
      of exceptional conditions, not just bad queries.  Replaced
      most of these in v2.0.0 with new dedicated exceptions, but a
      few remained:
      
      - Errors that occur during the processing of a "use" query after
        the query itself executes correctly now throw UseQueryError.
        It's not a "bad query", because the query executed
        successfully.  It just choked during subsequent processing,
        so it's a different exception.  Thanks for this patch go to
        Jim Wallace.


      - Replaced BadQuery exceptions thrown in Row constructor due
        to bad ctor parameters with new ObjectNotInitialized exception


        This is also Jim Wallace's work.

    o The examples now all use getopt() type command line options
      instead of positional options.  This makes it possible to
      pass options in any order, leave at their default options that
      used to be in the middle of the sequence, and offer different
      subsets of options for different programs.  Also allows for
      special internal-use options, like -D passed by dtest to let
      examples change their behavior when run under dtest to produce
      only predictable output.

    o Split old libutil functionality into two modules, one holding
      all the "print data" functions, and another holding all the
      command line parsing stuff.  This makes it easier for newbies
      to ignore the command line stuff, treating it like a black box.
      The wish to understand the "print data" routines is much more
      common, so the two needed to be disentangled.

    o Renamed examples' libutil to libexcommon.

    o Removed connect_to_db() libutil function.  It combined command
      line parsing, which users don't care about, with database
      connection establishment, which they do care about.  Now the
      examples just call out to libexcommon to parse the command
      line, and use the values they get back to explicitly make the
      connection, so it isn't hidden.

    o Removed cchar and uint typedefs.

    o Redesigned dbinfo example's output to be easier to read.

    o Fixed an output formatting bug created in 2.3.0 that caused the
      tabular output from examples to not line up.

    o Renamed examples/tquery.cpp to tquery1.cpp.  Created tquery2.cpp
      to demonstrate passing parameters via a SQLQueryParametrs object
      instead of discretely.  Created tquery3.cpp for testing unquoted
      template parameters, such as integers.

    o Renamed fieldinf1.cpp example to fieldinf.cpp, and simplified
      its output so it can be part of the dtest sequence.

    o Renamed examples/xaction.cpp to transaction.cpp.  It created too
      much cognotive dissonance whenever thinking about both it and
      lib/transaction.cpp.

    o Added examples/deadlock.cpp, to test handling of exceptions due
      to server-side transaction deadlock detection.  Also added
      code to resetdb to create a table needed to test this.
      Initial version created by Jim Wallace to test the value of
      all his BadQuery exception work, with reworking by me.

    o Greatly expanded dtest suite.  Primary change is that we now
      have a handful of unit tests, where in v2.3.2 we only tested
      a subset of the examples.  Still very low coverage ratio,
      but it's a big improvement.

    o Optimized #includes, especially in lib/*.h to reduce
      dependencies and thus compile time when one of these changes.

    o Fixed a typo in RPM filename generation that prevented -devel
      RPM from recognizing that the corresponding MySQL++ library
      RPM was installed.

    o RPM spec file improvements by Remi Collet.


    o Renamed NO_LONG_LONGS to MYSQLPP_NO_LONG_LONGS to avoid a risk
      of collision in the global macro namespace.
    
    o First cut at Xcode2 project support.  Testing needed!

    o Debug build of library on VC++ and Xcode have a _d suffix now
      so you can have both versions of the library installed without
      conflict.

    o Moved the VC++ 2003 project files into a new vs2003 subdirectory
      because there are so many of them.  Also created vs2005
      subdirectory for VC++ 2005 and 2008 compatible project files.
      2005 makes an even bigger mess of the directory containing
      the .sln file, so the incentive is bigger.  Plus, we have to
      disable several things to get VC++ 2003 to build MySQL++ now,
      so we need a special 2005+ version of the project files for a
      complete build, if the user has one of the newer compilers.

    o ...plus dozens of small bug fixes and internal enhancements,
      many documentation improvements, and expansion of support for
      newer operating systems and compilers.


2.3.2, 2007.07.11 (r1669)

    o Previous release's const_string change caused more problems
      than it fixed.  This release contains the real fix. :)

    o New Connection::set_option() handling deals with the multi
      statements option correctly again.  examples/multiquery now
      runs again as a result.

    o Added new unit testing script, called dtest.  See the
      HACKERS file for details.  (This tool caught the previous
      two problems!)

    o Squished a GCC pedantic warning.  Thanks for the patch go to
      Andrew Sayers.


2.3.1, 2007.07.10 (r1659) The "After the Fireworks" release

    o const_string objects now keep a copy of their data, not
      just a pointer to it.  This is less efficient, but necessary
      to allow SSQLS to work with BLOBs.  Without this, we were
      seeing segfaults due to accessing freed memory pointed to
      by the const_string, because the underlying object went
      out of scope.

    o Fixed many more potential embedded null handling problems
      in manip.h.

    o MySQL++ can now optionally reference MySQL C API headers as
      being in a mysql subdirectory, a common thing on *ix systems,
      by defining MYSQLPP_MYSQL_HEADERS_BURIED before #including
      mysql++.h.

    o Restored ColData_Tmpl<T>::get_string(), removed in v2.3.0,
      along with warnings in the docs saying why you don't want
      to use it, and what your alternatives are.

    o VC++ and MinGW builds now define the HAVE_MYSQL_SSL_SET
      macro, which lets you use the C API's SSL features.
      This assumes your C API library does actually have these
      features enabled, which is the case with the official binary
      releases on Windows.  (Builds on *ix systems continue to
      test for these features at configure time.)

    o Fixed simple examples-only Makefile generation, for RPMs.


2.3.0, 2007.07.02 (r1645)

    o Added Query::for_each() and Query::store_if() methods
      proposed by Joel Fielder, and added examples for each.

    o It's now possible to store BLOB data in an SSQLS.  It's not
      foolproof, so added a section to the user manual (5.9) to
      document the method.  Also, changed examples/cgi_jpeg to use
      this new mechanism, instead of the ugly "raw row data" method
      it used to use.

    o Revamped Connection::set_option() handling.  These options
      used to be queued up, and applied only just before actually
      establishing the connection.  This made error reporting less
      helpful because the diagnostic was separated from the cause.
      Plus, the error messages were misleading to begin with.  Now,
      set_option() takes effect immediately if the connection is not
      yet up (excepting one special option that can actually be set
      after the connection is up) and issues better diagnostics when
      it detects errors.

    o Connection::connect() used to set a few options in such a
      way that the user couldn't override them.  Now it's smart enough
      to set them with the desired default values only when we see
      that the user hasn't given them other values.

    o SQLString can now be initialized from a mysqlpp::null,
      giving a "NULL" string.  This is useful for template queries.
      Patch by Michael Hanselmann.

    o resetdb error message about mixing library and header version
      numbers is now more explicit.

    o Changed BadConversion exception's "what" message text to be
      more like the other exceptions.  The inconsistency lead one
      to incorrectly copy-paste code from another exception handler,
      expecting it to behave the same way.  Now it does.

    o Added Row::raw_size(), as a shortcut for Row::at().size().

    o ssqls-pretty now detects when it's being run from within
      the MySQL++ distribution tree and gives a different -I flag
      to the compiler, so that it picks up the distribution headers
      instead of those that may be on the system already.

    o The quote manipulator now works for char[] correctly.
      Thanks for this patch go to Andrew Sayers.  (It's always
      worked for char*, but C++ doesn't consider that to be the
      same type, so it used the generic quote handling path,
      which doesn't do anything for char[].)

    o Fixed a build bug on older Solaris versions where the
      test for the C API library was erroneously failing, stopping
      the configuration process.

    o Simplified mysql_shutdown() level argument detection.
      Already had to do a version number ifdef check for the
      Windows case, so there's really no point to doing it with
      autoconf on Unixy platforms.  Moved version number check
      into lib/connection.cpp, and nuked the separate autoconf and
      Windows tests.

    o Removed dependency of sql_types.h on myset.h and (indirectly)
      datetime.h.  Now we only define sql_* typedef aliases for those
      MySQL++ types if the headers are included before sql_types.h.

    o Fixed a typo in one of the storein_sequence() template
      overloads, which is apparently rarely (or never?) used, because
      no one reported the compiler error you'd get if you tried.

    o Fixed a few more embedded null handling problems.

    o ColData used to keep two copies of all data it held.
      Now it keeps just one.

    o Fixed install.bat script to track the unified Bakefile change
      and the lack of separate debug and release builds under MinGW.

    o Yet another STLport + Query memory leak fix.

    o Squished a warning in newer GCCs having to do with identifier
      shadowing.  Patch by Jonathan Wakely.

    o Fixed a null-termination bug in Query::parse().  If you
      somehow constructed a query string without a terminating null
      character, then tried to parse it as a template query, it could
      walk off the end of the string.  Patch by Worster Chen.

    o Removed MYSQLPP_EXPORT tag from FieldNames and FieldTypes
      class declarations, as this can cause problems in programs
      that use vector<string> in VC++.  It has to do with multiply
      defined templates, since these classes derive from that
      template, and VC++ can't resolve the conflict without help.
      Since these classes aren't actually used outside the library,
      this shouldn't cause a problem.  Patch by Nils Woetzel.

    o Partial fix to Doxygen PDF build on RHEL4 and 5.  Needs
      hand-coaxing to complete successfully on RHEL4, and doesn't
      yet work at all on RHEL5.

    o Shortened the "no*" options to the bootstrap script, so that
      the usage message fits on a single line.

    o Added "nodoc" bootstrap script option, for disabling the
      documentation build during the dist target build.  Allows for
      building binary RPMs on CentOS 5.0, where doc building is
      currently broken.

    o Removed the updel example program.  It was kind of silly,
      and if you were to rewrite it today, you'd use for_each() anyway.

    o Lots of documentation improvements.


2.2.3, 2007.04.17 (r1538) The "Tax Day" release

    o Previous version left examples/vstudio/* out of the tarball
      by accident.

    o Improved generation of RPM temporary build directory path
      name generation.  Was using a hacked variant of the Fedora
      Packaging Guidelines' second best choice.  Now we're using
      the choice they recommend most highly, without changes.

    o Removed unnecessary resources from vstudio/wforms example.

    o Minor URL fix in refman


2.2.2, 2007.04.13 (r1526) The "Nervousmaking Friday the 13th" release

    o More small fixes to embedded null handling in Query.

    o Fixed a bug in single-parameter template query handling.

    o Added tquery example, to demonstrate proper use of template
      queries.  Previously, resetdb was the only exemplar, and
      it wasn't really suited for that.  This example also tests
      the previous item.

    o Added examples/vstudio/mfc, allowing us to improve the way
      we demonstrate Unicode handling.  Old way wasn't realistic.
      On *ix, people will depend on the terminal code to handle
      UTF-8.  On Windows, users are almost certain to be writing
      a GUI program, which requires different Unicode handling
      than the old examples showed.

    o Removed explicit Unicode conversion stuff from command line
      examples, and reworked the Unicode chapter in the user
      manual.
    
    o Added examples/vstudio/wforms to show integration with
      C++/CLI and Windows Forms.  Documented this in README.vc.

    o Rewrote load_file and cgi_image examples to be more
      useful, renaming them to load_jpeg and cgi_jpeg along
      the way.  Also, resetdb now creates a second table in the
      sample database for these two examples' use.  Also, added
      examples/logo.jpg to the distribution as sample data for
      these examples.

    o Limited the ostream base class casting stuff in Query to
      VC++ 2003, which is the only platform that really needed it.
      VC++ 2005 emits a warning with that hack in place, and on
      other platforms it's just replicating work that the compiler
      does already.

    o Added library version information to main library target
      so that systems that version shared libraries work as
      expected.  Thanks for this patch go to Jack Eidsness.

    o Merged much of the diffs between Remi Collet's RPM spec file
      into the official one.

    o Reorganized the doc subdir a bit.  Generated HTML is now all
      under doc/html instead of scattered under other subdirs,
      and renamed doc/README.mysql++ to doc/README.manuals.

    o Improvements to top-level manual building make targets:
      manuals now only rebuild at need, it's easier to request
      a rebuild of all manuals, and we force a rebuild attempt
      before building the distribution tarball so we don't ship
      outdated manuals.

    o Added ability to run examples under gdb using exrun,
      using same mechanism as we currently have for valgrind.
      Thanks for this patch go to Michael Hanselmann.

    o Added "Important Underlying C API Limitations" chapter to the
      user manual, to cover problems we keep seeing on the
      mailing list that are the result of ignorance of the way
      libmysqlclient behaves, not bugs MySQL++ is really in a
      position to fix.


2.2.1, 2007.02.28 (r1433)

    o Fixed the new localtime() alternative selection code
      for VS2003 and various uses of STLport.


    o No longer inserting a null character into the query stream
      on calling one of the preview() functions.  This was harmless
      in v2.1, which used C strings more extensively, but began
      causing problems in v2.2 due to its wider use of C++ strings.

    o Fixed a bug in the Connection copy ctor where it didn't
      completely initialize the object.

    o Optimized Query::preview_char() a bit.  Patch by Jonathan
      Wakely.

    o Reordered directory list used by autconf when locating the
      MySQL C API library.  The list is now ordered with the
      most likely locations for the library first, so we're less
      distracted by incorrect libraries.  This fixes a specific
      build error under RHEL4 with recent versions of MySQL 5.0.


2.2.0, 2007.01.23 (r1417)

    o ColData, const_string, and SQLString can now be constructed
      with an explicit length parameter.  Furthermore, Query
      class's execute(), store() and use() call chains terminate
      in a version taking an explicit length parameter, instead
      of one taking a simple C string.  Together, this means
      that it's now easier to handle data from the SQL server
      containing nulls.  The library is almost certainly not yet
      capable of handling embedded nulls in all cases, but this
      is a big first step towards that.

    o Can now construct a DateTime object from a time_t, and
      convert a DateTime back to a time_t.  Patch by Korolyov Ilya.

    o Changed the way we're handling exported functions in the
      Windows DLL case so that it works more reliably under MinGW.

    o Added proper copy semantics to Connection, so that you get a
      new connection with the same parameters, not just a bitwise
      copy of the object.

    o Using an explicitly thread-safe variant of localtime() for
      time conversions where one is available.

    o Removed ListInsert template from myset.h.  This wasn't used
      within the library, and was never documented, so I'm betting
      that no one actually uses it.

    o Result::copy() was not copying the exception flag in
      all cases.  Fix by Steven Van Ingelgem.

    o Added exrun shell script and exrun.bat files to distribution,
      to avoid linkage errors when running the examples while
      you still have an older version of MySQL++ installed.

    o Renamed MYSQLPP_LIB_VERSION to MYSQLPP_HEADER_VERSION, as
      what it really encodes is the version number in the mysql++.h
      file you're using, not the actual library version number.

    o Added mysqlpp::get_library_version(), which returns the
      library version number at build time.  Between this and
      the header version constant, you can check that you're not
      mixing MySQL++ header and library versions.

    o resetdb example uses these new version number affordances to
      double-check that you're not mixing libraries and headers
      from different versions.  This happens easily unless you
      take care of it (such as by using exrun) when you have one
      version of MySQL++ installed and you're trying to build and
      test a new version without blowing away the old one first
      or overwriting it.

    o No longer using recursive Makefiles on Unixy platforms
      or split lib + examples project files on VC++.  Everything is
      handled by a single top-level Makefile or project file, which
      is simpler for the end user, and makes better dependency
      management possible.

    o When looking for the MySQL C library on systems using
      autoconf, looking in .../lib64 wherever we are also looking
      in .../lib.

    o RPM build process no longer depends on Bakefile.  It means
      you have to build the examples when building an RPM even
      though they're never used within the RPM, but it's a better
      tradeoff in my opinion.

    o Updated include and library paths on Windows to reflect
      changes in the most recent MySQL installers.

    o Merged lib/defs.h and lib/platform.h into new file,
      lib/common.h.  Just cleans up the library internals.

    o Fixed build errors on Windows due to recent changes in MySQL.

    o Fixed a few memory leaks and double-deletes in Query class.

    o Fixed compatibility with STLPort's string implementation.
      Patch by dengxy at cse.buaa.edu.cn.

    o Fixed a compatibility problem between Set<> template and
      SSQLS.  Patch by Korolyov Ilya.

    o Fixed build bug in SQLQueryParms due to a character
      signedness issue on PowerPC with GCC.  Patch by Michael
      Hanselmann.

    o ~Transaction() can no longer throw exceptions.  It'll just
      quietly eat them, to avoid program termination.  Fix
      suggested by Alex Burton.

    o Fixed thread safety testing in autoconf case, accidentally
      broken during v2.1.0 development cycle.

    o Using Doxygen 1.5.1 to generate documentation.


2.1.1, 2006.04.04 (r1289)

    o MinGW and Cygwin will now build and link to mysqlpp DLLs.

    o Fixed bug in Query, causing it to initialize the "throw
      exceptions" flag incorrectly.  Thanks for this patch go to
      Joel Fielder.

    o Added -v flag for custom.pl script, which turns off the
      multiply-defined static variable fix.  Needed for VS 2003,
      which doesn't support variadic macros.  Also, added
      a diagnostic to detect the need for the -v flag, and
      suppressed the test for this feature in examples/util.cpp.


2.1.0, 2006.03.24 (r1269)

    o Converted automake and makemake files to their equivalents in
      Bakefile format.

    o Added the Transaction class, which makes it easy to use
      transaction sets in MySQL++.

    o Added xaction example to test new Transaction class.

    o Resetdb example now creates its example table using the
      InnoDB storage engine, in order to test the new transaction
      support.  Resetdb also declares the table as using UTF-8
      text; this doesn't change anything, but it does correctly
      document what we're doing.

    o Added sql_types.h header, containing C++ typedefs
      corresponding to each MySQL column type.  Using those new
      types in the type_info module, and in the SSQLS examples.

    o Replaced the way we were handling the template query
      version of Query member functions, to allow an arbitrary
      number of template query parameters.  By default, we
      now support 25 parameters, up from the old limit of 12.
      It's now possible to change just one number, run a script,
      and have a new limit.

    o Connection class does a better job of returning error
      messages if you call certain member functions that depend
      on a connection to the server before the connection is
      established.

    o Updated libmysqlclient.def for newer versions of MySQL.  (Fixes
      build errors having to do with mysql_more_results() and
      mysql_next_result().

    o Replaced final use of strcpy() with strncpy().

    o custom.pl now runs without complaint in strict mode, with
      warnings turned on.  Thanks for this patch go to "Waba".

    o Fixed a bug in custom.pl where incorrect code would be
      generated for some SSQLS set() methods.  Thanks for this
      patch go to "Waba".

    o SSQLS structures now support long and unsigned long fields.
      Thanks for this patch go to "Waba".

    o It's now possible to put SSQLS definitions in a header
      file used by multiple modules in a program without
      getting multiple static member definition errors.  See the
      documentation for details.  Thanks for this patch go to
      Viktor Stark.

    o Moved the definition of the 'stock' SSQLS out of the
      custom*.cpp example files and into a new stock.h file.
      Also, #including that file in the util module to test out
      the new SSQLS multiple static definition fix.

    o Using all of the digits of precision guaranteed by the
      IEEE 754 spec when stringizing floating point numbers
      to build queries.  Previously, we would use the platform
      default, which can be as few as 6 digits.

    o Removed lib/compare.h.  Not used within the library, never
      documented, and nobody seems to want to defend it.



2.0.7, 2005.11.23 (r1147)

    o Added explicit mysqlpp namespace qualifiers to generated code in
      custom*.h so you can use SSQLS in places where it doesn't make
      sense to say "using namespace mysqlpp" before the declaration.
      Also updated some of the examples to not have this "using"
      declaration to make it clear to users that it isn't needed, if you
      want to use explicit namespace qualifiers as well.  Thanks for
      this patch to Chris Frey.

    o Removed an apparently useless unlock() call from ResUse; there is
      no nearby lock() call, so if this unlock() is in fact necessary,
      it shouldn't be here anyway, because the two calls should be
      nearby each other.  Thanks for this patch to Chris Frey.

    o Fixed Query ostream initialization bug affecting SunPro CC (at
      least).  While this bug violates the Standard, it doesn't affect
      many real compilers because they don't enforce this rule.  Fixed
      by Chris Frey.

    o Previously, we only used the C99 style "long long" support when
      building under GNU CC.  This is now the default.  This should
      allow the code to work under SunPro CC.

    o Added another dynamic cast needed for proper Query ostream
      subclass overloading under VC++.  (7.1 at least...)

    o Detecting whether MySQL is built with SSL support on platforms
      using autotools.  Needed on some old Sun systems, for instance.
      Thanks for this patch to Ovidiu Bivolaru.

    o Fixed a potential memory bug in ColData's conversion to SQL null.

    o Many minor packaging tweaks.  (README clarifications, file
      permission fixes, better adherence to GNU packaging standards,
      etc.)

    
2.0.6, 2005.09.28 (r1123)

    o Fixed makemake.bat so it works on cmd.exe, not just 4NT.

    o Documentation fixes.


2.0.5, 2005.09.13 (r1114)

    o Visual C++ build now requires GNU make.  It is tested to work
      with either the Cygwin or the MinGW versions.  The previous
      version of MySQL++ used nmake.  This change enabled the
      following features:

        o Debug and Release versions are both built into
          separate subdirectories.

        o Dependency tracking for release version works
          correctly now.  (Previously dependencies worked
          only for debug version.)

        o 'make clean' removes release version binaries
          in addition to debug versions.

    o MinGW makemake support updated to support new release/debug
      subdirectory system.  This is probationary support, since
      this code currently can't be built as a DLL.  As a result,
      it is no more useful than the Cygwin version, for licensing
      reasons.

    o Several fixes to allow building on Solaris 8.  These fixes may
      also help on other SVR4-derived systems.

    o Removed Borland C++ makemake support, because this version
      of the library does not work completely, and there seems
      to be almost no user interest in fixing it.
      
    o Clarified "Handling SQL Nulls" section of user manual's
      Tutorial chapter.


2.0.4, 2005.08.29 (r1076)

    o Made mysql_shutdown() second parameter autoconf check less
      sensitive to compiler pedantry.

    o VC++ library Makefile is now smart enough to re-create the
      import library, if it is deleted while leaving the DLL alone.

    o Added libmysqlclient.def to tarball.

    o Reworked most of the top-level README* files.

    o Renamed LGPL file to LICENSE.


2.0.3, 2005.08.25 (r1060)

    o Visual C++ makemake system updated to build both debug and
      release versions of library DLL.

    o Fixed bug in simple1 example that caused crashes on Windows.

    o Doing UTF-8 to ANSI text translation in simple examples now.

    o Previous two releases built libmysqlpp with wrong soname on
      autotools-based systems.  Fixed.


2.0.2, 2005.08.18 (r1050)

    o Fixes to makemake system for cmd.exe.

    o Fixed the case where the system's C++ library includes an slist
      implementation in namespace std.


2.0.1, 2005.08.17 (r1046)

    o Added new simple1 example, showing how to retrieve just one
      column from a table.  Old simple1 is now called simple2, and
      simple2 is likewise shifted to simple3.

    o Added custom6 example, showing how to do the same thing with
      SSQLS.

    o Updated user manual to cover new examples.

    o Was accidentally shipping Subversion crap with tarball.  Fixed.


2.0.0, 2005.08.16 (r1031) The "Excess Hair Removal" release

    THIS IS NOT A DROP-IN REPLACEMENT FOR MySQL++ v1.7!

    At minimum, you will have to recompile your program against
    this library.  You may also have to make code changes.
    Please see the "Incompatible Library Changes" chapter of
    the user manual for a guide to migrating your code to this
    new version:

        http://tangentsoft.net/mysql++/doc/html/userman/breakages.html

    o The library's shared object file name (soname) scheme has
      changed.  (This mainly affects POSIX systems.)
      
      The soname for the last 1.7.x releases of MySQL++ was
      libmysqlpp.so.4, meaning the fourth version of the library's
      application binary interface (ABI).  (The first ABI version
      in this scheme was that provided by 1.7.9.)  MySQL++
      2.0.0's soname is libmysqlpp.so.2.0.0.  Since the dynamic
      linker setup on some systems will create a symlink to
      that file called libmysqlpp.so.2, it's possible that this
      library could be confused with that for MySQL++ 1.7.19
      through .21, which also used this number.  Do not install
      this library on a system which still has binaries linked
      against that version of the library!

      The new scheme is {ABI}.{feature}.{bug fix}.  That is,
      the first number changes whenever we break the library's
      binary interface; the second changes when adding features
      that do not break the ABI; and the last changes when the
      release contains only internal bug fixes.  This means
      that we will probably end up with MySQL++ 3.0 and 4.0 at
      some point, so there will be further soname conflicts.
      Hopefully we can put these ABI changes off long enough
      to avoid any real problems.


    o autoconf now installs headers into $prefix/include/mysql++,
      instead of $prefix/include.  If you were using the
      --includedir configure script option to get this behavior
      before, you no longer need it.

    o Linux binary RPMs will henceforth include only the
      libmysqlpp.so.X.Y.Z file, and create any short names
      required, to allow multiple versions to be installed at
      once.  Currently, you cannot install two MySQL++ library
      RPMs at once, because they both have /usr/lib/libmysqlpp.so.X,
      for instance.


    o Replaced the Visual C++ and Borland C++ project files with
      a new "makemake" system, which creates Makefiles specific
      to a particular toolchain.  This new mechanism also supports
      MinGW and generic GCC-on-*ix.  This was done partly to reduce
      the number of places we have to change when changing the
      file names in MySQL++ or adding new ones, and partly so we're
      not tied to one particular version of each of these tools.

    o VC++ Makefiles create a DLL version of the library only
      now, so there's no excuse for LGPL violations now.
      This same mechanism should make DLL builds under other
      Windows compilers easy.

    o Added Connection::enable_ssl(), which enables encrypted
      connections to the database server using SSL.

    o Connection::create_db() and drop_db() now return true on
      success, not false.

    o Connection::create_db() and drop_db() use Query::exec()
      now, for efficiency, rather than Query::execute().

    o Removed Connection::infoo().  Apparently just there to
      save you from a typo when calling the info() method, since
      it was a mere alias.

    o Renamed Connection::real_connect() to connect(), gave
      several more of its parameters defaults, and removed old
      connect() function.  Then changed user manual and examples
      to use new APIs.

    o Replaced Connection::read_option() with new set_option()
      mechanism.  The name change matches the method's purpose
      better.  Functional changes are that it returns true on
      success instead of 0, it supports a broader set of options
      than read_option() did, and it enforces the correct option
      argument type.

    o You can now call Connection::set_option() before the
      connection is established, which will simply queue the option
      request up until the connection comes up.  If you use this
      feature, you should use exceptions, because that's the only
      way an option setting failure can be signalled in this case.

    o Removed query-building functions (exec*(), store*(),
      use()) from class Connection, and moved all the implementation
      code to class Query.  Query no longer delegates the final
      step of sending the query to the database server to
      Connection().

    o Added Connection::enable_ssl(), for turning on SSL support on
      a connection.

    o Extracted exception disabling mechanism out of the many
      classes that had the feature into a new OptionalExceptions
      base class, which all classes having this feature now
      derive from.  Also, removed all per-method exception
      handling flags.  Finally, added NoExceptions class.  With
      all of these changes, there is now a common way to disable
      exceptions with fine granularity on all objects that
      support the feature.

    o All custom MySQL++ exceptions now derive from the new
      Exceptions class.  This regularizes the exception interface
      and allows you to use a single catch() block if you want.

    o The "throw exceptions" flag is passed from parent to child
      in all situations now.  (Or if not, please report it as
      a bug.) This fulfills a promise made in the v1.7.9 user
      manual, with the cost being that some programs will see
      new exceptions thrown that they're not expecting.

    o Added a bunch of new exception types: BadOption,
      ConnectionFailed, DBSelectionFailed, EndOfResults,
      EndOfResultSets, LockFailed, and ObjectNotInitialized.
      Some of these replace the use of BadQuery, which in v1.7.x
      was a kind of generic exception, thrown when something more
      specific wasn't available.  Beware, this means that programs
      may start crashing after recompiling them under v2.0 due to
      uncaught exceptions, if they were only trying to catch BadQuery.

      There are additional instances where the library will
      throw new exceptions.  One is when calling a method that
      forces the internals to use an out-of-bounds index on a
      vector; previously, this would just make the program
      likely to crash.  Another is that the library uses the
      BadFieldName exception -- created in v1.7.30 -- in more
      apropos situations.

    o Renamed SQLQueryNEParms to BadParamCount, to match naming
      style of other concrete exception types.

    o Extracted lock()/unlock() functions from Connection and
      Query classes into a new Lockable interface class.  Locking
      is implemented in terms of a different class hierarchy, Lock,
      which allows multiple locking strategies with a single ABI.


    o Removed ResUse::eof().  It's based on a deprecated MySQL
      C API feature, and it isn't needed anyway.




    o Removed arrow operator (->) for iterator returned by Fields,
      Result and Row containers.  It was inherently buggy, because
      a correct arrow operator must return the address of an
      object, but the underlying element access functions in these
      classes (e.g. at()) return objects by value, of necessity.
      Therefore, this operator could only return the address of
      a temporary, which cannot be safely dereferenced.

    o Returned Row subscripting to something more like the
      v1.7.9 scheme: there are two operator[] overloads, one for an
      integer (field by index) and another for const char* (field
      by name).  lookup_by_name() has been removed.  Because row[0]
      is ambiguous again, added Row::at() (by analogy with STL
      sequence containers), which always works.

    o Collapsed two of the Row::value_list*() overloads into
      two other similar functions using default parameters.
      This changes the API, but the removed functions aren't
      used within the library, and I doubt they are used outside,
      either.

    o Merged RowTemplate into Row.

    o Merged SQLQuery class into Query class.


    o Query is now derived from std::ostream instead of
      std::stringstream, and we manage our own internal string
      buffer.

    o Moved SQLParseElement and SQLQueryParms into their own
      module, qparms.

    o Added multiple result set handling to Query.  MySQL 4.1
      and higher allow you to give multiple SQL statements in a
      single "store" call, which requires extensions to MySQL++
      so you can iterate through the multiple result sets.  Also,
      stored procedures in MySQL 5.0 reportedly return multiple
      result sets.  Thanks for the initial patch go to Arnon Jalon;
      I reworked it quite a bit.

    o Query::storein*() now supports more varieties of the
      nonstandard slist comtainer.  (Singly-linked version of
      STL std::list.)


    o Template query mechanism and user manual had several
      mismatches.  Made manual match actual behavior, or
      made library match documented behavior, as apropriate.
      Initial patch by Jürgen MF Gleiss, with corrections and
      enhancements by Warren Young.

    o Collapsed mysql_* date and time base classes' methods and
      data into the subclasses.  Also, DateTime no longer derives
      from Date and Time; you could get away with that in the
      old hierarchy, but now it creates an inheritance diamond,
      and allows unsupported concepts like comparing a Time to
      a DateTime.

    o Removed "field name" form of Row::field_list().  It was
      pretty much redundant -- if you have the field names, why
      do you need a list of field names?

    o ColData can convert itself to bool now.  Thanks for this
      patch go to Byrial Jensen.

    o Removed simp_list_b type; wasn't being used, and doesn't
      look to be useful for end-user code.

    o Several methods that used to take objects by value now
      do so by const reference, for efficiency.

    o Several variable and function renamings so that MySQL++
      isn't needlessly tied to MySQL.  Even if we never make
      the library work with other database servers, there's
      little point in tying this library to MySQL blindly.

    o Renamed all private data members of MySQL++ classes to
      have trailing underscores.

    o 'private' section follows 'public' section in all classes
      now.

    o Removed mysql++.hh and sqlplus.hh backwards-compatibility
      headers.

    o Added copy ctors to Date/Time classes so that they will
      work in SSQLS under GCC 4.0.0.  Without these, the compiler
      couldn't make the conversion from raw MySQL row data.

    o Fixed a bunch of GCC 4.0 pedantic warnings: added virtual
      dtors to all base classes, calling base class ctors from leaf
      classes, etc.

    o All warnings fixed under VC++ at warning level 3.  (Mostly
      harmless signedness and integer conversion stuff.)

    o Updated LGPL license/copyright comments at the top of
      several files to use FSF's new physical address.

    o Relicensed user manual under a close variant of the Linux
      Documentation Project License, as it's designed for
      documentation, which the LGPL is not.  Permission for this
      received from Kevin Atkinson and MySQL AB.

    o Added ABI and API breakages chapter to user manual.  It
      is basically a subset of this ChangeLog, with only the
      information an end-user must know when migrating between
      versions.

    o Reworked user manual's DocBook code quite a bit after
      reading Bob Stayton's book "DocBook XSL" 3/e.  Better handling
      of stylesheets, taking advantage of some superior DocBook
      features, prettier output (especially the HTML version), etc.

    o Rewrote doc/userman/README to make it clearer how to get
      started contributing to the user manual.  It's essentially a
      "getting started with DocBook" guide now!

    o Lots of small text improvements to user and reference
      manuals.  Aside from the obvious tracking of library changes,
      made a bunch of minor style and clarity improvements.

    o Added CSS stylesheets for userman and refman to
      make the HTML versions of each a) not ugly; and b) match
      tangentsoft.net.  (Yes, some may say that these are incompatible
      goals....)


    o Standardized exception handling code in the examples that
      use it.

    o Fixed a potential memory leak due to exceptions thrown from
      ResUse.  Thanks for this patch go to Chris Frey.

    o Using new "no exceptions" feature of library in simple1
      example, so it is now truly simple.

    o simple1 example no longer depends as much on util module, so
      that all of the important code is in one place.  Makes
      learning MySQL++ a little less intimidating.

    o Added new simple2 and usequery examples, to demonstrate
      the proper way to handle a "use" query, with exceptions
      disabled, and not, respectively.  Added them to the user
      manual, in the appropriate place.

    o Refactored the "print stock table" example functions
      again, to make code using them clearer.

    o UTF-8 to UCS-2 handling in examples is now automatic on
      Windows.

    o Removed debug code from Windows Unicode output examples
      that slipped into previous release.

    o resetdb example is now clearer, and more robust in the
      face of database errors.

    o Simplified connect_to_db() in examples' util module.

    o Added sample autoconf macro for finding MySQL++ libraries, for
      people to use in their own autotools-based projects.

    o Lots and lots of minor cleanups not worth mentioning
      individually...


1.7.40, 2005.05.26 (r719)

    o Multiple item form of insert() now works if you're using the
      SQLQuery class, or its derivative, Query.  Thanks to Mark
      Meredino for this patch.

    o Fixed a bug in const_string::compare(), in which MySQL++
      would walk off the end of the shorter of the two strings.
      All was well if the two were the same length.

    o ResUse::operator=() now fully updates the object, so it's more
      like the behavior of the full ctor.

    o All source files now contain a license and copyright statement
      somewhere within them.

    o Optimized mysql++.h a bit: it now #includes only the minimum set
      of files required, and there is now an idempotency guard.
      This improves compile times a smidge, but mainly it was
      done to clean up the generated #include file graph in the
      reference manual.  Before, it was a frightful tangle because
      we #included everything except custom*.h.

    o Constness fix in MySQL++ date/time classes to avoid compiler
      warnings with SSQLS.  Thanks to Wolfram Arnold for this patch.

    o Fixed some compiler warnings in custom*.h.  Thanks to Chris Frey
      for this patch.

    o Added "Submitting Patches" and "Maintaining a Private CVS
      Repository" sections to the HACKERS file.  Thanks to Chris
      Frey for the source material for these sections.  The HACKERS
      file was improved in several other ways at the same time.

    o PDF version of user manual no longer has links to the reference
      manual.  They were ugly, and they were broken anyway due to the
      way we move the PDFs after generating them.  If you want
      interlinked manuals, use the HTML version.

    o PDF version of user manual now has hard page breaks between
      chapters.

    o Removed complic1 example.  Wasn't pulling its own weight.
      Everything it is supposed to demonstrate is shown in other
      examples already.

    o Refactored print_stock_table() in examples/util module to be
      four functions, and made all the examples use various of
      these functions where appropriate.  Before, several of
      the examples had one-off stock table printing code because
      print_stock_table() wasn't exactly the right thing, for one
      reason or another.  One practical problem with this is that
      some of the examples missed out on the recent Unicode updates;
      now such a change affects all examples the same way.

    o Since so many of the examples rely on the util module, the user
      manual now covers it.  The simple1 example in the user manual
      didn't make much sense before, in particular, because it's
      really just a driver for the util module.

    o Added custom5 example.  It shows how to use the equal_list()
      functionality of SSQLS.  Thanks to Chris Frey for the original
      version of this program.  (I simplified it quite a bit after
      accepting it.)

    o New user manual now covers the value_list(), equal_list() and
      field_list() stuff that the old manual covered but which was
      left out in previous versions of the new manaul.  Most of the
      examples are the same, but the prose is almost completely new.
      This new section includes the custom5 example.

    o Every declaration in MySQL++ is now documented in the reference
      manual, or explicitly treated as "internal only".



    o Improved docs for MySQL++'s mechanism to map between MySQL
      server types and C++ types.  Initial doc patch by Chris Frey,
      which I greatly reworked.

    o Improved a lot of existing reference manual documentation while
      adding the new stuff.

    o Expanded greatly on the exception handling discussion in the user
      manual.

    o Added all-new "Quoting and Escaping" section to the user
      manual's Tutorial chapter.  Moved some existing comments on
      quoting and escaping around and added some new ones to other
      sections as a result.

    o Added all-new "Handling SQL Nulls" section to the user manual's
      Tutorial chapter.

    o Many improvements to the Overview section of the user manual.

    o Row::operator[] reference now explains the right and wrong way to
      use the values it returns.  This is in response to a mailing list
      post where someone was incorrectly using this feature and getting
      a bunch of dangling pointers.

    o Updated Doxyfile so 1.3.19.1 parses it without warnings.  Still
      works with versions back to 1.2.18, at least.  (These are
      the versions shipped with Fedora Core 3 and Red Hat Linux 9,
      respectively.)

    o Using a superior method to make Doxygen ignore certain sections
      of the source code.  Between this change and the fact that
      everything not so ignored is documented, Doxygen no longer
      generates any warnings.

    o Lots of code style updates.  Everything should now be consistently
      formatted.


1.7.35, 2005.05.05 (r601) The "Cinco de Mayo" release

    o Added a "how to use Unicode with MySQL++" chapter to the user
      manual.  (Too bad "Cinco de Mayo" doesn't have any accented
      characters.  That would be just _too_ precious.)

    o VC++ examples now use the Unicode Win32 APIs, so they can display
      Unicode data from MySQL++.

    o Added an optional conversion function to examples/util.cpp to
      handle the conversion from UTF-8 to UCS-2 on Win32.

    o Moved "brief history of MySQL++" from intro section of refman to
      intro section of userman.

    o Lots of small bits of documentation polishing.
    
    o Made some minor constness fixes.  Thanks to Erwin van Eijk
      for this patch.

    o Made some warning fixes for GCC 4.0.  Not all warnings are
      fixed, because some of the needed changes would break the ABI.
      Thanks to Chris Frey for this patch.

    o Added lib/Doxyfile to distribution.
    

1.7.34, 2005.04.30 (r573)

    o Added a multiple-insert method for Query, which lets you insert
      a range of records from an STL container (or the whole thing,
      if you like) in a single SQL query.  This is faster, and it
      reduces coding errors due to less repetition.  Thanks to Mark
      Meredino for the patch.

    o Reference and user manual now get rebuilt automatically when
      required.  (E.g. on 'make dist', or explicitly now through 'make
      docs'.)

    o Made it easier to change the maximum number of SSQLS data members
      in generated custom-macros.h file.  It used to be hard-coded in
      several places in lib/custom.pl; now it's a variable at the top of
      the file.

    o Changed default SSQLS data member limit to 25, which is what it
      has been documented as for a long time now.  It was actually 26
      within custom.pl.

    o Fixed a regression in previous version.

    o Trimmed some fat from the distribution packages.

    o Some more small doucmentation improvements.


1.7.33, 2005.04.29 (r555)

    o Worked around an overloaded operator lookup bug in VC++ 7.1
      that caused SSQLS insert, replace and update queries to get
      mangled.  (Symptom was that custom2 and custom3 examples didn't
      work right.)  Thanks to Mark Meredino for digging up the
      following, which explains the problem and gives the solution:

      http://groups-beta.google.com/group/microsoft.public.vc.stl/browse_thread/thread/9a68d84644e64f15

    o Some VC++ warning fixes.

    o Major documentation improvements:
    
        o Using DocBook for user manual and Doxygen for reference
          manual.  The former now references the latter where
          useful.

        o Split out HACKERS and CREDITS files from main README,
          and improved remaining bits of README.

        o Moved the text from the old v1.7.9 LaTeX-based
          documentation over into the new systems, and reworked
          it to more closely resemble English.

        o Added a lot of new material to documentation, and
          simplified a lot of what already existed.

        o Documentation is now being built in HTML and PDF forms.

    o ebuild file updated to take advantage of recent configure script
      features.  Thanks to Chris Frey for this patch.



1.7.32, 2005.03.10 (r479)

    o Example building may now be skipped with --disable-examples
      configure script flag.

    o Changed stock items added in resetdb.  One is now UTF-8 encoded,
      to show that basic use of Unicode with MySQL++ is easy, yet not
      foolproof.  (See formatting of table on systems where cout isn't
      UTF-8 aware!)  Other stock items now follow a theme, for your
      amusement.  :)

    o custom3 example now changes UTF-8 item's name to the 7-bit ASCII
      equivalent.  Previously, this example would fix a spelling error
      in the table.

    o resetdb example now says 'why' when it is unable to create the
      sample database.

    o Small formatting change to print_stock_table(), used by several
      examples.

    o Was issuing a VC++-specific warning-disable pragma when built by
      any Windows compiler.  Fixed.
    

1.7.31, 2005.03.05 (r462) The "Inevitable Point-one Followup" release

    o Check for threads support must now be explicitly requested via
      configure script's new --enable-thread-check flag.

    o Fix for contacting MySQL server on a nonstandard port number.
      Thanks to Chris Frey for this patch.

    o Example programs using standard command line format now accept a
      fourth optional parameter, a port number for the server.  Thanks
      to Chris Frey for this patch.

    o One more g++ 3.4 pedantic warning fix by Chris Frey.

    o Exception handling in resetdb is no longer nested, because you'd
      get a segfault on some systems when an exception was thrown from
      one of the inner try blocks.

    o Improvements to Connection class's handling of locking mechanism.
      Concept based on patches by Rongjun Mu.

    o Implemented the declared-but-never-defined Query::lock().  Thanks
      to Rongjun Mu for this patch.
    
    o Cleaned up some unclear if/else blocks in connection.cpp by
      adding explicit braces, correct indenting and putting normal
      code path in the if side instead of the else.


1.7.30, 2005.02.28 (r443) The "Power of Round Numbers" release

    o bootstrap script now accepts a 'pedantic' argument, which sets a
      bunch of CFLAGS that make g++ very picky about the code it
      accepts without warnings.
      
    o Fixed a bunch of things that generated warnings with g++ in
      pedantic mode. Only two warnings remain, having to do with
      floating point comparisons.  (See Wishlist for plans on how to
      deal with these.)  Thanks to Chris Frey for this patch.

    o Split long tests out of configure.in into M4 files in new config
      subdir.  This makes configure.in easier to read.

    o Added preliminary thread support.  Currently, this just means that
      we detect the required compiler and linker thread flags, and link
      against the proper thread-safe libraries.  THERE MAY BE
      UN-THREAD-SAFE CODE IN MYSQL++ STILL!

    o Standard C++ exceptions are the default now.  Old pre-Standard
      exception stuff removed.

    o Row::lookup_by_name() will throw the new BadFieldName exception if
      you pass a bad field name.  Thanks for this patch to Chris Frey.

    o Row::operator[] will throw a Standard C++ out of bounds exception
      by way of std::vector::at() if you pass it a bad index.  Thanks
      for this patch to Chris Frey.

    o Setting Connection::is_connected flag to false on close().
      Previously, is_connected() would continue to return true after
      close() was called.

    o All number-to-string conversion ctors in SQLString class now use
      ostringstream to do the conversion.  Previously, we used
      snprintf(), which isn't available on all systems.  Also, we used a
      C99 format specifier for the "long long" conversion, which is also
      not available on all systems.  This new ostringstream code should
      be platform-independent, finally.


1.7.28, 2005.02.04 (r403)

    o --with-mysql* flags to configure script now try the given
      directory explicitly, and only if that fails do they try
      variations, like tacking '/lib' and such onto it to try and find
      the MySQL includes and libraries.  Thanks to Matthew Walton for
      the patch.

    o Finally removed sql_quote.h's dependence on custom.h, by moving
      the one definition it needed from custom.h to deps.h.  This will
      help portability to compilers that can't handle the SSQLS macros,
      by making that part of the library truly optional.


1.7.27, 2005.01.12 (r395)

    o configure check for libmysqlclient now halts configuration if the
      library isn't found.  Previously, it would just be flagged as
      missing, and MySQL++ would fail to build.

    o Added sql_string.cpp to VC++ and BCBuilder project files.

    o Removed Totte Karlsson's 'populate' example, which never made it
      into the distribution anyway.

    o Removed last vestiges of 'dummy.cpp'.

    o Renamed *.cc to *.cpp in BCBuilder project files.

    o Worked around a BCBuilder C++ syntax processing bug in row.h.


1.7.26, 2004.12.17 (r382)

    o Moved all of the SQLString definitions out of the header and into
      a new .cpp file, reformatted it all, and made the integer
      conversion functions use snprintf() or _snprintf() instead of
      sprintf().  Also, widened some of the buffers for 64-bit systems.

    o Using quoted #include form for internal library headers, to avoid
      some problems with file name clashes.  (The headers should still
      be installed in their own separate directory for best results,
      however.)  Thanks to Chris Frey and Evan Wies for the patch and
      the discussion that lead to it.

    o Removed unnecessary semicolons on namespace block closures.
      Thanks to Evan Wies for this patch.

    o Fixed namespace handling in the legacy headers mysql++.hh and
      sqlplus.hh.  Thanks to Chris Frey for this patch.

    o #including iostream instead of ostream in lib/null.h for
      broader C++ compatibility.  (This may allow MySQL++ to work on GCC
      2.95.2 again, but this is unconfirmed.)

    o Detecting proper mysql_shutdown() argument handling automatically
      in platform.h for the Windows compiler case instead of making the
      user edit the file.  Thanks to Evan Wies for this patch.
    
    o Fixed examples/Makefile.simple to use new *.cpp file naming.

    o Fix to Gentoo ebuild file's exception configure switch handling.
      Thanks to Chris Frey for this patch.

    o Rebuilding lib/custom*.h intelligently now, to avoid unnecessary
      recompiles after running bootstrap script.


1.7.25, 2004.12.09 (r360)

    o Yet more fixes to the --with-mysql-lib and --with-mysql-include
      flags.

    o Added DLLEXPORT stuff to platform.h, hopefully so that someone
      can figure out how to make VC++ make a DLL version of MySQL++.

    o Renamed *.cc to *.cpp.

    o Made 'set -> myset' change in VC++ project files.

    o Some style changes (mostly whitespace) in header files.


1.7.24, 2004.12.08 (r343)

    o Fixed the --with-mysql-lib and --with-mysql-include flags'
      behavior, and extended their search ability to handle one other
      common case.  (Fixed by Steve Roberts)

    o Fixes to put freestanding functions in namespace mysqlpp.  (They
      weren't in the namespace, while all the class member functions
      were.)  This required bumping the ABI version number to 4.
      
    o Renamed set module to myset, to avoid conflicts with Standard C++
      Library's set.h when MySQL++ headers were installed into one of
      the standard system include directories.

    o Renamed all the idempotency guards to make them consistent in
      style and unique to MySQL++.

    o Reformatted all of lib/*.cc.


1.7.23, 2004.11.20 (r333)

    o Query::reset() now empties the stored query string.  If you
      subsequently stored a longer query in the object, you'd overwrite
      the previous query, but otherwise the longer part of the previous
      one would stick out past the new query.

    o We now look to the NO_LONG_LONGS macro only to decide whether to
      fake 64-bit integer support using 32-bit integers.

    o 64-bit integer support under Visual C++ may be working now, using
      that platform's __int64_t type.  This has not been tested.

    o Removed 64-bit integer support for Codewarrior on Mac OS 9 and
      earlier.  OS X uses GCC, so it requires no special support.

    o Added MinGW detection in platform.h.
    
    o If you pass a flag (-X) to the examples that take the standard
      parameters (resetdb, simple1, etc.), it prints a usage message.
    
    o Better error handling in resetdb example, where errors are the
      most critical.  (If that one runs without errors, the others
      probably will, too, and you have to run that one first.)

    o resetdb now reports success, rather than succeeding silently.

    o Removed the code in sample1 example that duplicated util module's
      print_stock_table(), and called that function instead.

    o Moved the preview() calls in the example programs to before the
      query execution calls, because execution modifies the query.

    o All examples that take the standard command line parameters now 
      exit when connect_to_db() fails in one of the ways that don't
      throw an exception, rather than bulling onward until the next
      MySQL database call fails because the connection isn't up.

    o dbinfo example now takes the standard command line parameters.

    o Much better output formatting in dbinfo example.


    o Calling reset() where appropriate in the various example programs.
      Before, the programs may have worked, but not for the right
      reason.  This lead some people to believe that calling reset()
      was not necessary.

    o Fixed an incorrect use of row["string"] in complic1 example.

    o Lots of code style improvements to the examples.

    o Some VC++ type warnings squished.  Some remain.
    

1.7.22, 2004.11.17 (r302)

    o Applied patches by Zahroof Mohammed to allow it to build under GCC
      3.4.2.  Tested on MinGW and Fedora Core 3 systems.

    o Removed all the forward declarations in defs.h, and added
      forward declarations where necessary in individual header files.
      #including defs.h in fewer locations as a result.

    o Legacy headers sqlplus.hh and mysql++.hh now declare they are
      using namespace mysqlpp, to allow old code to compile against the
      new library without changes.

    o Removed query_reset parameter from several class Query member
      functions.  In the implementation, these parameters were always
      overridden!  No sense pretending that we pay attention to these
      parameters.  This changes the ABI version to 3.

    o #including custom.h in sql_query.h again...it's necessary on GCC
      3.4.
    
    o bootstrap script runs lib/config.pl after configure.  This is
      just a nicety for those running in 'maintainer mode'.


1.7.21, 2004.11.05 (r273)

    o Generating a main mysql++ RPM containing just the library files
      and basic documentation, and the -devel package containing
      everything else.

    o Devel package contains examples now, along with a new Makefile
      that uses the system include and library files, rather than the
      automake-based Makefile.am we currently have which uses the files
      in the mysql++ source directory.

    o Renamed sqlplusint subdirectory in the package to lib.

    o Removed the obsolete lib/README file.

    o lib/sql_query.h no longer #includes custom.h, simplifying
      build-time dependencies and shortening compile times.


1.7.20, 2004.11.03 (r258)

    o Collapsed all numbered *.hh headers into a single *.h file.  For
      example, the contents of row1.hh, row2.hh and row3.hh are now in
      row.h.

    o While doing the previous change, broke several circular
      dependencies.  (The numbered file scheme was probably partly done
      to avoid this problem.)  The practical upshot of most of these
      changes is that some functions are no longer inline.

    o Removed define_short.hh and everything associated with it.  The
      library now uses the short names exclusively (e.g. Row instead of
      MysqlRow).

    o Put all definitions into namespace mysqlpp.  For most programs,
      simply adding a 'using namespace mysqlpp' near the top of the
      program will suffice to convert to this version.

    o Once again, the main include file was renamed, this time to
      mysql++.h.  Hopefully this is the last renaming!

    o mysql++.hh still exists.  It emits a compiler warning that the
      file is obsolete, then it #includes mysql++.h for you.

    o sqlplus.hh is back, being a copy of the new mysql++.hh.  Both of
      these files may go away at any time.  They exist simply to help
      people transition to the new file naming scheme.

    o Renamed mysql++-windows.hh to platform.h, and added code to it to
      handle #inclusion of config.h on autotools-based systems
      intelligently.  This fixes the config.h error when building under
      Visual C++.

    o There is now only one place where conditional inclusion of
      winsock.h happens: platform.h.

    o Beautified the example programs.


1.7.19, 2004.10.25 (r186)

    o Fixed an infinite loop in the query mechanism resulting from the
      strstream change in the previous version.  There is an overloaded
      set of str() member functions that weren't a problem when query
      objects were based on strstream.
     
    o Query mechanism had a bunch of const-incorrectness: there were
      several function parameters and functions that were const for
      the convenience of other parts of the code, but within these
      functions the constness was const_cast away!  This was evil
      and wrong; now there are fewer const promises, and only one is
      still quietly broken within the code.  (It's in the SQLQuery
      copy ctor implementation; it should be harmless.)

    o Removed operator=() in Query and SQLQuery classes.  It cannot take
      a const argument for the same reason we have to cast away const
      in the SQLQuery copy ctor.  It's tolerable to do this in the copy
      ctor, but intolerable in an operator.  Since the copy ctor is good
      enough for all code within the library and within my own code, I'm
      removing the operator.

    o Above changes required bumping the ABI to version 2.

    o Visual C++ projects now look for MySQL build files in c:\mysql,
      since that's the default install location.  (Previously, it was
      c:\program files\mysql.)


1.7.18, 2004.10.01 (r177)

    o Changed all the strstream (and friends) stuff to stringstream type
      classes.  Let there be much rejoicing.

    o Query object now lets you use store() even when the SQL query
      cannot return a result, such as a DROP TABLE command.  This is
      useful for sending arbitrary SQL to the server.  Thanks to
      Jose Mortensen for the patch.

    o Quote fix in configure.in, thanks to David Sward.

    o Renamed undef_short file to undef_short.hh.

    o Gentoo ebuild file is actually being shipped with the tarball,
      instead of just sitting in my private CVS tree since 1.7.14 was
      current.  Ooops....


1.7.17, 2004.09.16 (r170)

    o Reverted one of the VC++ warning fix changes from 1.7.16 that
      caused crashes on Linux.

    o Added a configure test that conditionally adds the extra 'level'
      parameter to mysql_shutdown() that was added in MySQL 4.1.3 and
      5.0.1.


1.7.16, 2004.09.13 (r160)

    o Building VC++ version with DLL version of C runtime libraries, and
      at warning level 3 with no warnings emitted.

    o VC++ build no longer attempts to fake "long long" support.  See
      the Wishlist for further thoughts on this.


1.7.15, 2004.09.02 (r144)

    o Renamed Configure file to common.am, to avoid file name conflict
      with configure script on case-sensitive file systems.

    o Added ebuild file and ebuild target to top-level Makefile for
      Gentoo systems.  Thanks to Chris Frey for this.

    o Small efficiency improvements to BadQuery exception handling.
      Initial idea by Chris Frey, improvements by Warren Young.


1.7.14, 2004.08.26 (r130)

    o Builds with Visual C++ 7.1.

    o Fixed a bug in custom macro generation that caused problems with
      GCC 3.4.  (X_cus_value_list ctor definition was broken.)


1.7.13, 2004.08.23 (r92)

    o Removed USL CC support.  (System V stock system compiler.)  Use
      GCC on these platforms instead.

    o Added examples/README, explaining how to use the examples, and
      what they all do.

    o Most of the example programs now accept command line arguments for
      host name, user name and password, like resetdb does.

    o Renamed sinisa_ex example to dbinfo.

    o Several Standard C++ syntax fixes to quash errors emitted by
      GCC 3.4 and Borland C++ Builder 6.  Thanks to Steffen Schumacher
      and Totte Karlsson for their testing and help with these.

    o Added proper #includes for BCBuilder, plus project files for same.
      Thanks to Totte Karlsson for these.


1.7.12, 2004.08.19 (r63)

    o Many Standard C++ fixes, most from the GCC 3.4 patch by
      Rune Kleveland.

    o Added Wishlist file to distribution.

    o Fixed a problem in the bootstrap script that caused complaints
      from the autotools on some systems.

    o RPM building is working properly now.

    o Fixed the idempotency guard in datetime1.hh.


1.7.11, 2004.08.17 (r50)

    o Renamed mysql++, defs and define_short files, adding .hh to the
      end of each.  (They're header files!)  This shouldn't impact
      library users, since these are hopefully used internal to the
      library only.

    o Removed sqlplus.hh file.  Use mysql++.hh instead.
    
    o Added mysql++.spec, extracted from contributed 1.7.9 source RPM, 
      and updated it significantly.  Also, added an 'rpm' target to
      Makefile.am to automate the process of building RPMs.

    o Added bootstrap and LGPL files to distribution tarball.

    o Added pre-1.7.10 history to this file.

    o Removed .version file.  Apparently it's something required by old
      versions of libtool.


1.7.10, 2004.08.16 (r27)

    o Maintenance taken over by Warren Young (mysqlpp at etr dash usa
      dot com.) See http://lists.mysql.com/plusplus/3326 for details.

    o Applied many of the GCC 3.x patches submitted for 1.7.9 over
      the years.  This allows it to build on everything from 3.0 to
      3.3.3, at least.  Because so many patches are rolled up in one
      big jump, it's difficult to describe all the changes and where
      they came from.  Mostly they're Standard C++ fixes, as GCC
      has become more strict in the source code that it will accept.

    o MysqlRow used to overload operator[] for string types as well as
      integers so you could look up a field by its name, rather than by
      its index.  GCC 3.3 says this is illegal C++ due to ambiguities in
      resolving which overload should be used in various situations.
      operator[] is now overloaded only for one integer type, and a
      new member function lookup_by_name() was added to maintain the old
      by-field-name functionality.

    o Fixed another operator overloading problem in SSQLS macro
      generation with GCC 3.3.

    o The _table member of SSQLS-defined structures is now const char*,
      so you can assign to it from a const char* string.

    o Got autoconf/automake build system working with current versions
      of those tools again.  Removed the generated autotools files from
      CVS.

    o Renamed library file from libsqlplus to libmysqlpp.


1.7.9 (May 1 2001) Sinisa Milivojevic <sinisa@mysql.com>

    * Fixed a serious bug in Connection constructor when reading MySQL
    * options
    * Improved copy constructor and some other methods in Result /
    * ResUse
    * Many other minor improvements
    * Produced a complete manual with chapter 5 included
    * Updated documentation, including a Postscript format

1.7.8 (November 14 2000) Sinisa Milivojevic <sinisa@mysql.com>

    * Introduced a new, standard way of dealing with C++ exceptions.
    * MySQL++ now supports two different methods of tracing exceptions.
    * One is by the fixed type (the old one) and one is standard C++
    * type by the usage of what() method. A choice of methods has to be
    * done in building a library. If configure script is run with
    * -enable-exception option , then new method will be used. If no
    * option is provided, or -disable-exception is used, old MySQL++
    * exceptions will be enforced. This innovation is a contribution of
    * Mr. Ben Johnson <ben@blarg.net>
    * MySQL++ now automatically reads at connection all standard MySQL
    * configuration files
    * Fixed a bug in sql_query::parse to enable it to parse more then 99
    * char's
    * Added an optional client flag in connect, which will enable usage
    * of this option, e.g. for getting matched and not just affected
    * rows. This change does not require any changes in existing
    * programs
    * Fixed some smaller bugs
    * Added better handling of NULL's. Programmers will get a NULL
    * string in result set and should use is_null() method in ColData to
    * check if value is NULL
    * Further improved configuration
    * Updated documentation, including a Postscript format

1.7.6 (September 22 2000) Sinisa Milivojevic <sinisa@mysql.com>

    * This release contains some C++ coherency improvements and scripts
    * enhacements
    * result_id() is made available to programmers to fetch
    * LAST_INSERT_ID() value
    * Connection constroctur ambiguity resolved, thanks to marc@mit.edu
    * Improved cnnfigure for better finding out MySQL libraries and
    * includes
    * Updated documentation, including a Postscript format

1.7.5 (July 30 2000) Sinisa Milivojevic <sinisa@mysql.com>


    * This release has mainl bug fixes  and code improvements
    * A bug in FieldNames::init has been fixed, enabling a bug free
    * usage of this class with in what ever a mixture of cases that is
    * required
    * Changed behaviour of ResUse, Result and Row classes, so that they
    * could be re-used as much as necessary, without any memory leaks,
    * nor with any re-initializations necessary
    * Fixed all potential leaks that could have been caused by usage of
    * delete instead of delete[] after memory has been allocated with
    * new[]
    * Deleted all unused classes and macros. This led to a reduction of
    * library size to one half of the original size. This has
    * furthermore brought improvements in compilation speed
    * Moved all string manipulation from system libraries to
    * libmysqlclient, thus enabling uniformity of code and usage of 64
    * bit integers on all platforms, including Windows, without
    * reverting to conditional compilation. This changes now requires
    * usage of mysql 3.23 client libraries, as mandatory
    * Changed examples to reflect above changes
    * Configuration scripts have been largely changed and further
    * changes shall appear in consecutive sub-releases. This changes
    * have been done and shall be done by our MySQL developer Thimble
    * Smith <tim@mysql.com>
    * Changed README, TODO and text version of manual. Other versions of
    * manual have not been updated
    * Fixed .version ``bug''. This is only partially fixed and version
    * remains 1.7.0 due to some problems in current versions of libtool.
    * This shall be finally fixed in a near future
    * Several smaller fixes and improvements
    * Added build.sh script to point to the correct procedure of
    * building of this library. Edit it to add configure options of your
    * choice





1.7 (May17 2000) Sinisa Milivojevic <sinisa@mysql.com>





    * This is mainly a release dealing with bug fixes, consistency
    * improvements and easier configure on some platforms
    * A bug in fetch_row() method of ResUse class has been fixed. Beside
    * changes that existed in a distributed patch, some additional error
    * checking has been introduced
    * A bug in escape manipulator has been fixed that could cause an
    * error if all characters had to be escaped
    * An inconsistency in column indexing has been fixed. Before this
    * version, column names in row indexing with strings, i.e.
    * row[<string>] , has been case sensitive, which was inconsistent
    * with MySQL server handling of column names
    * An inconsistency in conversion from strings to integers or floats
    * has been fixed. In prior version a space found in data would cause
    * a BadConversion exception. This has been fixed, but 100%
    * consistency with MySQL server has not been targeted, so that other
    * non-numeric characters in data will still cause BadConversion
    * exception or error. As this API is used in applications, users
    * should provide feedback if full compatibility with MySQL server is
    * desired, in which case BadConversion exception or error would be
    * abolished in some of future versions
    * A new method in ColData class has been introduced. is_null()
    * method returns a boolean to denote if a column in a row is NULL.
    * Finally, as of this release, testing for NULL values is possible.
    * Those are columns with empty strings for which is_null() returns
    * true.
    * Some SPARC Solaris installations had C++ exception problems with
    * g++ 2.95.2 This was a bug that was fixed in GNU gcc, as from
    * release 2.95 19990728. This version was thoroughly tested and is
    * fully functional on SPARC Solaris 2.6 with the above version of
    * gcc.
    * A 'virtual destructor ' warning for Result class has been fixed
    * Several new functions for STL strings have been added. Those
    * functions (see string_util.hh) add some of the functionality
    * missing in existing STL libraries
    * Conversion for 64 bit integers on FreeBSD systems has been added.
    * On those systems _FIX_FOR_BSD_ should be defined in CXXFLAGS prior
    * to configuring. Complete conversion to the usage of functions for
    * integer conversion found in mysqlclient library is planned for one
    * of the next releases
    * A completely new, fully dynamic, dramatic and fully mutable result
    * set has been designed and will be implemented in some of 2.x
    * releases
    * Several smaller fixes and improvements, including defaulting
    * exceptions to true, instead of false, as of this version
    * An up-to-date and complete Postscript version of documentation is
    * included in this distribution
    * Large chunks of this manual are changed, as well as README and
    * TODO files.

1.6 (Feb 3 2000) Sinisa Milivojevic <sinisa@mysql.com>


    * This is a major release as it includes new features and major
    * rewrites
    * Automatic quoting and escaping with streams. It works
    * automatically , depending on the column type. It will work with <<
    * on all ostream derived types. it is paricularly handy with query
    * objects and strstreams. Automatic quoting and escaping on cout,
    * cerr and clog stream objects is intentionally left out, as quoting
    * / escaping on those stream objects is not necessary. This feature
    * can be turned of by setting global boolean dont_quote_auto to
    * true.
    * Made some major changes in code, so that now execute method should
    * be used only with SSQL and template queries, while for all other

    * query execution of UPDATE's, INSERT's, DELETE's, new method exec()
    * should be used. It is also faster.
    * New method get_string is inroduced for easier handling / casting
    * ColData into C++ strings.
    * Major rewrite of entire code, which led to it's reduction and
    * speed improvement. This also led to removal of several source
    * files.
    * Handling of binary data is introduced. No application program
    * changes are required. One of new example programs demonstrates
    * handling of binary data
    * Three new example programs have been written and thoroughly
    * tested. Their intention is to solve some problems addressed by
    * MySQL users.
    * Thorough changes is Makefile system has been made
    * Better configuration scripts are written, thanks to D.Hawkins
    * <dhawkins@cdrgts.com>
    * Added several bug fixes
    * Changed Manual and Changelog

1.5 (Dec 1 1999) Sinisa Milivojevic <sinisa@mysql.com>

    * Fixed bug in template queries, introduced in 1.4 (!)
    * Fixed connect bug
    * Fixed several bug in type_info classes
    * Added additional robustness in classes
    * Added additional methods for SQL type info
    * Changed Changelog and README

1.4 (Nov 25 1999) Sinisa Milivojevic <sinisa@mysql.com>

    * Fixed bug in store and storein methods
    * Fixed one serious memory leak
    * Fixed a very serious bug generated by gcc 2.95.xx !!
    * Added robustness in classes, so that e.g. same query and row
    * objects can be re-used
    * Changed sinisa_ex example to reflect and demonstrate this
    * stability
    * Changed Changelog and README
    * Few other bug fixes and small improvements and speed-ups

1.3 (Nov 10 1999) Sinisa Milivojevic <sinisa@mysql.com>


    * Fixed several erronous definitions
    * Further changed source to be 2.95.2 compatible
    * Expunged unused statements, especially dubious ones, like use of
    * pointer_tracker
    * Corrected bug in example file fieldinf1
    * Finally fixed mysql_init in Connection constructor, which provided
    * much greater stability !
    * Added read and get options, so that clients, like mysqlgui can use
    * it
    * Changed Changelog and README
    * Many other bug fixes.






1.2 (Oct 15 1999) Sinisa Milivojevic <sinisa@mysql.com>

    * First offical release. Version 1.0 and 1.1 were releases by Sinisa
    * before I (Kevin Atkinson) made him the offical maintainer,
    * Many manual fixes.
    * Changed README and Changelog
    * Changed source to be compilable by gcc 2.95.xx, tribute to Kevin
    * Atkinson <kevinatk@home.com>
    * Added methods in Connection class which are necessary for
    * fullfilling administrative functions with MySQL
    * Added many bug fixes in code pertaining to missing class
    * initializers , as notified by Michael Rendell <michael@cs.mun.ca>
    * Sinisa Milivojevic <sinisa@mysql.com> is now the offical
    * maintainer.

1.1 (Aug 2 1999) Sinisa Milivojevic <sinisa@mysql.com>

    * Added several bug fixes
    * Fixed memory leak problems and variables overlapping problems.
    * Added automake and autoconf support by loic@ceic.com
    * Added Makefile for manual
    * Added support for cygwin
    * Added example sinisa_ex (let modesty prevail) which used to crash
    * a lot when memory allocation, memory leak and overlap problems
    * were present. Smooth running of this example proves that all those
    * bugs are fixed
    * Corrected bugs in sql_query.cc regarding delete versus delete[]
    * and string length in manip.cc
    * Changed manual
    * Changed README
    * Many other smaller things

1.0 (June 9 1999) Michael Widenius <monty@monty.pp.sci.fi>

    * Added patches from Orion Poplawski <orion@bvt.com> to support the
    * UnixWare 7.0 compiler

.64.1.1a (Sep 27 1998)

    * Fixed several bugs that caused my library to fail to compile with
    * egcs 1.1. Hopefully it will still compile with egcs 1.0 however I
    * have not been able to test it with egcs 1.0.
    * Removed some problem causing debug output in sql++pretty.

.64.1a (Aug 1 1998)

    * Added an (almost) full guide to using Template Queries.
    * Fixed it so the SQLQuery will throw an exception when all the
    * template parameters are not provided.
    * Proofread and speedchecked the manual (it really needed it).
    * Other minor document fixes.

.64.0.1a (July 31 1998)

    * Reworked the Class Reference section a bit.
    * Minor document fixes
    * Added more examples for SSQLS.
    * Changed the syntax of equal_list for SSQLS from equal_list (cchar
    * *, Manip, cchar *) to (cchar *, cchar *, Manip).
    * Added set methods to SSQLS. These new methods do the same thing as
    * there corresponding constructors.
    * Added methods for creating a mysql_type_info from a C++ type_info.

.64.a (July 24 1998)

    * Changed the names of all the classes so they no longer have to
    * have Mysql in the begging of it. However if this creates a problem
    * you can define a macro to only use the old names instead.
    * The Specialized SQL Structures (formally known as Custom Mysql


    * Structures) changed from mysql_ to sql_.
    * Added the option of using exceptions thoughout the API.
    * ColData (formally known as MysqlStrings) will now throw an
    * exception if there is a problem in the conversion.
    * Added a null adapter.
    * Added Mutable Result Sets
    * Added a very basic runtime type identification for SQL types
    * Changed the document format from POD to LYX .
    * Am now using a modified version of Perceps to extract the class
    * information directly from the code to make my life easier.
    * Added an option of defining a macro to avoid using the automatic
    * conversion with binary operators.
    * Other small fixed I probully forgot to mentune.

.63.1.a

    * Added Custom Mysql Structures.
    * Fixed the Copy constructor of class Mysql
    * Started adding code so that class Mysql lets it children now when
    * it is leaving
    * Attempted to compile it into a library but still need help. As
    * default it will compile as a regular program.
    * Other small fixes.

.62.a (May 3 1998)


    * Added Template Queries
    * Created s separate SQLQuery object that is independent of an SQL
    * connection.
    * You no longer have to import the data for the test program as the

    * program creates the database and tables it needs.
    * Many small bug fixes.

.61.1.a (April 28 1998)

    * Cleaned up the example code in test.cc and included it in the
    * manual.
    * Added an interface layout plan to the manual.
    * Added a reverse iterator.
    * Fixed a bug with row.hh (It wasn't being included because of a
    * typo).

.61.0.a

    * Major interface changes. I warned you that the interface may
    * change while it is in pre-alpha state and I wasn't kidding.
    * Created a new and Separate Query Object. You can no longer execute
    * queries from the Mysql object instead you have to create a query
    * object with Mysql::query() and use it to execute queries.
    * Added the comparison operators to MysqlDate, MysqlTime and
    * MysqlDateTime. Fixed a few bugs in the MysqlDate... that effected
    * the stream output and the conversion of them to strings.
    * Reflected the MysqlDate... changes in the manual.
    * Added a new MysqlSet object and a bunch of functions for working
    * with mysql set strings.

.60.3a (April 24 1998)

    * Changed strtoq and strtouq to strtoll and strtull for metter
    * compatibility Minor Manual fix.
    * Changed makefile to make it more compatible with Solaris (Thanks
    * Chris H)
    * Fixed bug in comparison functions so that they would compare in he
    * right direction.
    * Added some items to the to do list be sure to have a look.

Changes to lib/noexceptions.h.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
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
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
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
144
145
146
147
148
149
150
151
152
153
154
155
/// \file noexceptions.h
/// \brief Declares interface that allows exceptions to be optional
///
/// A class may inherit from OptionalExceptions, which will add to it
/// a mechanism by which a user can tell objects of that class to
/// suppress exceptions.  (They are enabled by default.)  This module
/// also declares a NoExceptions class, objects of which take a
/// reference to any class derived from OptionalExceptions.  The
/// NoExceptions constructor calls the method that disables exceptions,
/// and the destructor reverts them to the previous state.  One uses
/// the NoExceptions object within a scope to suppress exceptions in
/// that block, without having to worry about reverting the setting when
/// the block exits.

/***********************************************************************
 Copyright (c) 2005-2007 by Educational Technology Resources, Inc.
 Others may also hold copyrights on code in this file.  See the
 CREDITS.txt file in the top directory of the distribution for details.

 This file is part of MySQL++.

 MySQL++ is free software; you can redistribute it and/or modify it
 under the terms of the GNU Lesser General Public License as published
 by the Free Software Foundation; either version 2.1 of the License, or
 (at your option) any later version.

 MySQL++ is distributed in the hope that it will be useful, but WITHOUT
 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
 License for more details.

 You should have received a copy of the GNU Lesser General Public
 License along with MySQL++; if not, write to the Free Software
 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
 USA
***********************************************************************/

#ifndef MYSQLPP_NOEXCEPTIONS_H
#define MYSQLPP_NOEXCEPTIONS_H

#include "common.h"

namespace mysqlpp {

#if !defined(DOXYGEN_IGNORE)
// Make Doxygen ignore this
class MYSQLPP_EXPORT NoExceptions;
#endif

/// \brief Interface allowing a class to have optional exceptions.
///
/// A class derives from this one to acquire a standard interface for
/// disabling exceptions, possibly only temporarily.  By default,
/// exceptions are enabled.
///
/// Note that all methods are const even though some of them change our
/// internal flag indicating whether exceptions should be thrown.  This
/// is justifiable because this is just an interface class, and it
/// changes the behavior of our subclass literally only in exceptional
/// conditions.  This Jesuitical interpretation of "const" is required
/// because you may want to disable exceptions on const subclass
/// instances.
///
/// If it makes you feel better about this, consider that the real
/// change isn't within the const OptionalExceptions subclass instance.
/// What changes is the code wrapping the method call on that instance
/// that can optionally throw an exception.  This outside code is in
/// a better position to say what "const" means than the subclass
/// instance.

class MYSQLPP_EXPORT OptionalExceptions
{
public:
	/// \brief Default constructor
	///
	/// \param e if true, exceptions are enabled (this is the default)
	OptionalExceptions(bool e = true) :
	exceptions_(e)
	{
	}

	/// \brief Destroy object
	virtual ~OptionalExceptions() { }

	/// \brief Enable exceptions from the object
	void enable_exceptions() const { exceptions_ = true; }

	/// \brief Disable exceptions from the object
	void disable_exceptions() const { exceptions_ = false; }

	/// \brief Returns true if exceptions are enabled
	bool throw_exceptions() const { return exceptions_; }

protected:
	/// \brief Sets the exception state to a particular value
	///
	/// This method is protected because it is only intended for use by
	/// subclasses' copy constructors and the like.
	void set_exceptions(bool e) const { exceptions_ = e; }

	/// \brief Declare NoExceptions to be our friend so it can access
	/// our protected functions.
	friend class NoExceptions;

private:
	mutable bool exceptions_;
};


/// \brief Disable exceptions in an object derived from
/// OptionalExceptions.
///
/// This class was designed to be created on the stack, taking a
/// reference to a subclass of OptionalExceptions. (We call that our
/// "associate" object.) On creation, we save that object's current
/// exception state, and disable exceptions. On destruction, we restore
/// our associate's previous state.

class MYSQLPP_EXPORT NoExceptions
{
public:
	/// \brief Constructor
	///
	/// Takes a reference to an OptionalExceptions derivative,
	/// saves that object's current exception state, and disables
	/// exceptions.
	NoExceptions(const OptionalExceptions& a) :
	assoc_(a),
	exceptions_were_enabled_(a.throw_exceptions())
	{
		assoc_.disable_exceptions();
	}

	/// \brief Destructor
	///
	/// Restores our associate object's previous exception state.
	~NoExceptions()
	{
		assoc_.set_exceptions(exceptions_were_enabled_);
	}
	
private:
	const OptionalExceptions& assoc_;
	bool exceptions_were_enabled_;

	// Hidden assignment operator and copy ctor, because we should not
	// be copied.
	NoExceptions(const NoExceptions&);
	NoExceptions& operator=(const NoExceptions&);
};

} // end namespace mysqlpp

#endif // MYSQLPP_NOEXCEPTIONS_H

|
<
<
<
<
<
|
<
<
<
<
<
<

<
|

|



















<
<
<
|


<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
|
<
<
<
<
<
<
|
<
<
<
|
<
<
<
<
<

<
<
<
<
1





2






3

4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25



26
27
28


























































































29






30



31





32




/***********************************************************************





 null.cpp - Defines a few things declared in null.h








 Copyright (c) 2007 by Educational Technology Resources, Inc.
 Others may also hold copyrights on code in this file.  See the
 CREDITS file in the top directory of the distribution for details.

 This file is part of MySQL++.

 MySQL++ is free software; you can redistribute it and/or modify it
 under the terms of the GNU Lesser General Public License as published
 by the Free Software Foundation; either version 2.1 of the License, or
 (at your option) any later version.

 MySQL++ is distributed in the hope that it will be useful, but WITHOUT
 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
 License for more details.

 You should have received a copy of the GNU Lesser General Public
 License along with MySQL++; if not, write to the Free Software
 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
 USA
***********************************************************************/




#include "null.h"

namespace mysqlpp {


























































































	/// \brief "NULL" string constant used in many places within MySQL++






	const std::string null_str("NULL");



}










Changes to lib/null.cpp.




1







2






3







4
5








6





















7







8





9



10
11






12




13



















14


15

16

17

18



19



20
21







22


23


24























25



26




27





28
29
30









31
























32



/***********************************************************************







 null.cpp - Defines a few things declared in null.h














 Copyright (c) 2007 by Educational Technology Resources, Inc.
 Others may also hold copyrights on code in this file.  See the








 CREDITS.txt file in the top directory of the distribution for details.





























 This file is part of MySQL++.









 MySQL++ is free software; you can redistribute it and/or modify it
 under the terms of the GNU Lesser General Public License as published






 by the Free Software Foundation; either version 2.1 of the License, or




 (at your option) any later version.






















 MySQL++ is distributed in the hope that it will be useful, but WITHOUT

 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or

 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public

 License for more details.







 You should have received a copy of the GNU Lesser General Public
 License along with MySQL++; if not, write to the Free Software







 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301


 USA


***********************************************************************/



























#include "null.h"










namespace mysqlpp {
	/// \brief "NULL" string constant used in many places within MySQL++
	const std::string null_str("NULL");









}

























>
>
>
|
>
>
>
>
>
>
>
|
>
>
>
>
>
>

>
>
>
>
>
>
>
|
|
>
>
>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

>
>
>
>
>
>
>
|
>
>
>
>
>

>
>
>
|
|
>
>
>
>
>
>
|
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

>
>
|
>
|
>
|
>
|
>
>
>

>
>
>
|
|
>
>
>
>
>
>
>
|
>
>
|
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

>
>
>
|
>
>
>
>

>
>
>
>
>
|
|
|
>
>
>
>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
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
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
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
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
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
Visual C++ Version Compatibility
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    MySQL++ is fully functional with Visual C++ 2005 and 2008.

    MySQL++ also works with VC++ 2003 (a.k.a. VC++ 7.1), with the
    exception of the SSQLS feature.  There was partial support for
    SSQLS with VC++ 2003 in MySQL++ v2, but a feature we added in
    MySQL++ v3.0 crashes this version of the compiler, so we had to
    remove support for it entirely.  MySQL++ automatically disables
    SSQLS when you build it with VC++ 2003.  As long as you avoid
    using that feature of the library, you should be fine.

    Older versions of Visual C++ are basically hopeless when it
    comes to building current versions of MySQL++.  They have too
    many weaknesses in their Standard C++ implementation to build a
    modern library like MySQL++.  If you cannot upgrade your compiler,
    my advice is that you're best off programming straight to the
    MySQL C API rather than try to make MySQL++ build.

    There are two sets of .sln and .vcproj files shipped with MySQL++:
    one for Visual C++ 2003 in the vc2003 subdirectory, and another
    set for VC++ 2005 and newer in vc2005.  The only difference
    between them is that the VC++ 2003 versions omit SSQLS related
    files from the build.  If you're using VC++ 2008, use the vc2005
    project files; Visual Studio will walk you through the conversion
    process, which will do the right thing.


Prerequisites
~~~~~~~~~~~~~
    You need to have the Windows version of the MySQL server installed
    on your development system, even if you always access a MySQL
    server on a different machine.  This is because in addition to
    installing the server itself, the official MySQL Windows binaries
    also install the client-side development files that MySQL++
    needs in order to communicate with a MySQL server.

    You have to do a Custom install to enable installation of these
    development files.  If you get an error about mysql-version.h or
    mysql.h when building MySQL++, go back and reinstall the MySQL
    server, paying careful attention to the options.

    If you've installed the development files and are still getting
    header file include errors, read on.


Building the Library and Example Programs
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    If you installed the MySQL server somewhere other than 
    
        C:\Program Files\MySQL\MySQL Server 5.0\
        
    you need to change the project file settings.  If you're willing to
    install Bakefile (see below), you can do this quickly by changing
    the variable MYSQL_WIN_DIR at the top of the file mysql++.bkl,
    then regenerating the project files by running rebake.bat.
    Otherwise, you'll need to change the include and library paths
    in all of the project files by hand.

    You must build both the Debug and Release versions of the library,
    because a release build of your program won't work with a Debug
    version of the MySQL++ DLL.  Since version 3.0, the VC++ build
    of MySQL++ names these two DLLs differently: mysqlpp_d.dll for
    the Debug version, and mysqlpp.dll for the Release version.
    This lets you keep them in the same PATH directory, without a
    concern as to whether the correct one will be used.

    With the library built, run at least the resetdb and simple1
    examples to ensure that the library is working correctly.
    In addition to the other generic examples, there are a few
    Visual C++ specific examples that you might want to look at in
    examples\vstudio.  See README-examples.txt for further details.

    Once you're sure the library is working correctly, you can run
    the install.bat file at the project root to automatically install
    the library files and headers in subdirectories under c:\mysql++.


Using MySQL++ in an MFC Project
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    If you don't already have a project set up, open Visual Studio,
    say File > New > Project, then choose Visual C++ > MFC > MFC
    Application.  Go through the wizard setting up the project as
    you see fit.

    Once you have your project open, right click on your top-level
    executable in the Solution Explorer, choose Properties, and make
    the following changes.  (Where it doesn't specify Debug or Release,
    make the same change to both configurations.)

        o Append the following to C/C++ > General > Additional Include
          Directories:

            C:\Program Files\MySQL\MySQL Server 5.0\include,
            C:\mysql++\include

        o Under C/C++ > Code Generation change "Runtime Library" to
          "Multi-threaded Debug DLL (/MDd)" for the Debug
          configuration.  For the Release configuration, make it
          "Multi-threaded DLL (/MD)".

        o Append the following to Linker > General > Additional Library
          Directories for the Debug configuration:

            C:\Program Files\MySQL\MySQL Server 5.0\lib\debug,
            C:\mysql++\vc\debug

          For the Release configuration, make it the same, but
          change the 'debug' directory names to 'opt'.

        o Under Linker > Input add the following to "Additional
          Dependencies" for the Debug configuration:

            libmysql.lib wsock32.lib mysqlpp_d.lib

          ...and then for the Release configuration:
          
            libmysql.lib wsock32.lib mysqlpp.lib

          This difference is because MySQL++'s Debug DLL and import
          library have a _d suffix so you can have both in the same
          directory without conflicts.

    You may want to study examples\vstudio\mfc\mfc.vcproj to see
    this in action.  Note that some of the paths will be different,
    because it can use relative paths for mysqlpp.dll.


Using MySQL++ in a Windows Forms C++/CLI Project
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    Before you start work on getting MySQL++ working with your own
    program, you need to make some changes to the MySQL++ build
    settings.  Open mysqlpp.sln, then right-click on the mysqlpp
    target and select Properties.  Make the following changes for
    both the Debug and Release configurations:

        o Under Configuration Properties > General, change "Common
          Language Runtime support" to the /clr setting.

        o Under C/C++ > Command Line, remove the /EHsc from the
          Additional Options section.

    If you have already built MySQL++, be sure to perform a complete
    rebuild after changing these options.  The compiler will emit
    several C4835 warnings after making those changes, which are
    harmless when using the DLL with a C++/CLI program, but which warn
    of real problems when using it with unmanaged C++.  As a result,
    it's probably best if you don't install the resulting DLL in a
    system level directory.  I'd recommend copying it only into the
    same directory as the EXE.

    Once you have MySQL++ built with CLR support, open your program's
    project.  If you don't already have a project set up, open Visual
    Studio, say File > New > Project, then choose Visual C++ > CLR >
    Windows Forms Application.  Go through the wizard setting up the
    project as you see fit.

    The configuration process isn't much different from that for an
    MFC project, so go through the list above first.  Then, make the
    following changes particular to .NET and C++/CLI:

        o Under Configuration Properties > General change the setting
          from /clr:pure to /clr.  (You need mixed assembly support
          to allow a C++/CLI program to use a plain C++ library
          like MySQL++.)

        o For the Linker > Input settings, you don't need wsock32.lib.
          The mere fact that you're using .NET takes care of that
          dependency for you.

    In the MFC instructions above, it said that you need to build it
    using the Multi-threaded DLL version of the C++ Runtime Library.
    That's not strictly true for MFC, but it's an absolute requirement
    for C++/CLI.  See the Remarks in this MSDN article for details:

        http://msdn2.microsoft.com/en-us/library/k8d11d4s.aspx

    You may want to study examples\vstudio\wforms\wforms.vcproj to
    see all this in action.  Note that some of the paths will be
    different, because it can use relative paths for mysqlpp_d.dll
    and mysqlpp.dll.


Working With Bakefile
~~~~~~~~~~~~~~~~~~~~~
    MySQL++'s top-level Visual Studio project files aren't
    maintained directly.  Instead, we use a tool called Bakefile
    (http://bakefile.org/) to generate many different project file
    and Makefile types from a single set of source files.  There is
    a native Windows version of Bakefile up on that web site.
    Download that and put the directory containing bakefile_gen.exe
    in your Windows PATH.

    Bakefile generates the various project files and Makefiles from
    a single source file, mysql++.bkl.  This is usually the file you
    need to change when you want to make some change to the MySQL++
    build system.

    While Bakefile's documentation isn't as comprehensive as it
    ought to be, you can at least count on it to list all of the
    available features.  So, if you can't see a way to make Bakefile
    do something, it's likely it just can't do it.  Bakefile is a
    high-level abstraction of build systems in general, so it'll never
    support all the particulars of every odd build system out there.

    Once you've made your changes, you can generate the Visual C++
    project files by running rebake.bat, which you can find in the
    same directory as this file.


If You Run Into Problems...
~~~~~~~~~~~~~~~~~~~~~~~~~~~
    Especially if you have linking problems, make sure your project
    settings match the above.  Visual C++ is very picky about things
    like run time library settings.  When in doubt, try running one
    of the example programs.  If it works, the problem is likely in
    your project settings, not in MySQL++.

Changes to lib/null.h.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
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
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76

77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98



99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
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
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
191
192

193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230

231
232
233
234



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
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
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
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
/// \file null.h
/// \brief Declares classes that implement SQL "null" semantics within
/// C++'s type system.
///
/// This is required because C++'s own NULL type is not semantically
/// the same as SQL nulls.

/***********************************************************************
 Copyright (c) 1998 by Kevin Atkinson, (c) 1999-2001 by MySQL AB, and
 (c) 2004-2008 by Educational Technology Resources, Inc.  Others may
 also hold copyrights on code in this file.  See the CREDITS.txt file
 in the top directory of the distribution for details.

 This file is part of MySQL++.

 MySQL++ is free software; you can redistribute it and/or modify it
 under the terms of the GNU Lesser General Public License as published
 by the Free Software Foundation; either version 2.1 of the License, or
 (at your option) any later version.

 MySQL++ is distributed in the hope that it will be useful, but WITHOUT
 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
 License for more details.

 You should have received a copy of the GNU Lesser General Public
 License along with MySQL++; if not, write to the Free Software
 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
 USA
***********************************************************************/

#ifndef MYSQLPP_NULL_H
#define MYSQLPP_NULL_H

#include "exceptions.h"

#include <iostream>
#include <string>

namespace mysqlpp {

extern const std::string null_str;	///< "NULL" string constant


/// \brief The type of the global mysqlpp::null object.
///
/// User code shouldn't declare variables of this type.  Use the
/// Null template instead.
class MYSQLPP_EXPORT null_type
{
protected:
#if !defined(DOXYGEN_IGNORE)
// Doxygen will not generate documentation for this section.
	template <typename CannotConvertNullToAnyOtherDataType>
	operator CannotConvertNullToAnyOtherDataType() const
	{
		return CannotConvertNullToAnyOtherDataType();
	}
#endif // !defined(DOXYGEN_IGNORE)
};

/// \brief Global 'null' instance.  Use wherever you need a SQL null.
///
/// SQL null is equal to nothing else.  It is not the same as C++'s
/// NULL value, it is not a Boolean false....it is unique.  As such, if
/// you use this in some other type context, you will get a compiler
/// error saying something about \c CannotConvertNullToAnyOtherDataType.
/// The only thing you can assign this object instance to is a variable
/// of type Null<T>, and then only directly.  Code like this does not
/// work:
///
/// \code
/// int foo = return_some_value_for_foo();
/// mysqlpp::Null<int> bar = foo ? foo : mysqlpp::null;
/// \endcode
/// 

/// The compiler will try to convert mysqlpp::null to \c int to make
/// all values in the conditional operation consistent, but this is
/// not legal.  Anyway, it's questionable code because it means you're
/// using SQL null to mean the same thing as zero here.  If zero is a
/// special value, there's no reason to use SQL null.  SQL null exists
/// when every value for a particular column is legal and you need
/// something that means "no legal value".
const null_type null = null_type();


/// \brief Class for objects that define SQL null in terms of
/// MySQL++'s null_type.
///
/// Returns a null_type instance when you ask what null is, and is
/// "(NULL)" when you insert it into a C++ stream.
///
/// Used for the behavior parameter for template Null
struct NullIsNull
{
#if !defined(DOXYGEN_IGNORE)
// Doxygen will not generate documentation for this section.
	static null_type null_is() { return null; }




	static std::ostream& null_ostr(std::ostream& o)
	{
		o << "(NULL)";
		return o;
	}
#endif // !defined(DOXYGEN_IGNORE)
};


/// \brief Class for objects that define SQL null as 0.
///
/// Returns 0 when you ask what null is, and is zero when you insert it
/// into a C++ stream.
///
/// Used for the behavior parameter for template Null
struct NullIsZero
{
#if !defined(DOXYGEN_IGNORE)
// Doxygen will not generate documentation for this section.
	static int null_is() { return 0; }
	
	static std::ostream& null_ostr(std::ostream& o)
	{
		o << 0;
		return o;
	}
#endif // !defined(DOXYGEN_IGNORE)
};

/// \brief Class for objects that define SQL null as a blank C string.
///
/// Returns "" when you ask what null is, and is empty when you insert
/// it into a C++ stream.
///
/// Used for the behavior parameter for template Null
struct NullIsBlank
{

#if !defined(DOXYGEN_IGNORE)
// Doxygen will not generate documentation for this section.
	static const char *null_is() { return ""; }
	
	static std::ostream& null_ostr(std::ostream& o)
	{
		o << "";
		return o;
	}
#endif // !defined(DOXYGEN_IGNORE)
};


/// \brief Class for holding data from a SQL column with the NULL
/// attribute.
///
/// This template is necessary because there is nothing in the C++ type
/// system with the same semantics as SQL's null.  In SQL, a column can
/// have the optional 'NULL' attribute, so there is a difference in 
/// type between, say an \c int column that can be null and one that
/// cannot be.  C++'s NULL constant does not have these features.
///
/// It's important to realize that this class doesn't hold nulls,
/// it holds data that \e can \e be null.  It can hold a non-null
/// value, you can then assign null to it (using MySQL++'s global
/// \c null object), and then assign a regular value to it again; the
/// object will behave as you expect throughout this process.
///
/// Because one of the template parameters is a C++ type, the typeid()
/// for a null \c int is different than for a null \c string, to pick
/// two random examples.  See type_info.cpp for the table SQL types that
/// can be null.
template <class Type, class Behavior = NullIsNull>
class Null
{
public:
	/// \brief The object's value, when it is not SQL null

	Type data;



	
	/// \brief If set, this object is considered equal to SQL null.
	///
	/// This flag affects how the Type() and << operators work.
	bool is_null;




	/// \brief Type of the data stored in this object, when it is not
	/// equal to SQL null.
	typedef Type value_type;

	/// \brief Default constructor
	///
	/// "data" member is left uninitialized by this ctor, because we
	/// don't know what to initialize it to.
	Null() :
	data(),
	is_null(false)
	{

	}

	/// \brief Initialize the object with a particular value.
	///
	/// The object is marked as "not null" if you use this ctor.  This
	/// behavior exists because the class doesn't encode nulls, but
	/// rather data which \e can \e be null.  The distinction is
	/// necessary because 'NULL' is an optional attribute of SQL
	/// columns.
	Null(const Type& x) :
	data(x),
	is_null(false)
	{
	}

	/// \brief Construct a Null equal to SQL null
	///
	/// This is typically used with the global \c null object. (Not to
	/// be confused with C's NULL type.)  You can say something like...
	/// \code
	/// Null<int> foo = null;
	/// \endcode
	/// ...to get a null \c int.
	Null(const null_type&) :
	data(),
	is_null(true)
	{
	}

	/// \brief Converts this object to Type
	///
	/// If is_null is set, returns whatever we consider that null "is",
	/// according to the Behavior parameter you used when instantiating
	/// this template.  See NullIsNull, NullIsZero and NullIsBlank.
	///
	/// Otherwise, just returns the 'data' member.
	operator Type() const
	{

		if (is_null) {
			return Behavior::null_is();
		}
		else {



			return data;
		}
	}

	/// \brief Assign a value to the object.
	///
	/// This marks the object as "not null" as a side effect.
	Null& operator =(const Type& x)
	{
		data = x;

		is_null = false;
		return *this;

	}

	/// \brief Assign SQL null to this object.
	///
	/// This just sets the is_null flag; the data member is not
	/// affected until you call the Type() operator on it.
	Null& operator =(const null_type&)
	{
		is_null = true;
		return *this;
	}

	/// \brief Do equality comparison of two nullable values
	///
	/// Two null objects are equal, and null is not equal to not-null.
	/// If neither is null, we delegate to operator == for the base
	/// data type.
	bool operator ==(const Null<Type>& rhs) const
	{
		if (is_null && rhs.is_null) {
			return true;
		}
		else if (is_null != rhs.is_null) {
			return false;	// one null, the other not
		}
		else {
			return data == rhs.data;
		}
	}

	/// \brief Do equality comparison against hard-coded SQL null
	///
	/// This tells you the same thing as testing is_null member.
	bool operator ==(const null_type&) const { return is_null; }


	/// \brief Do inequality comparison of two nullable values
	bool operator !=(const Null<Type>& rhs) const
			{ return !(*this == rhs); }

	/// \brief Do inequality comparison against hard-coded SQL null
	bool operator !=(const null_type& rhs) const


			{ return !(*this == rhs); }

	/// \brief Do less-than comparison of two nullable values

	///
	/// Two null objects are equal to each other, and null is less
	/// than not-null.  If neither is null, we delegate to operator <

	/// for the base data type.
	bool operator <(const Null<Type>& rhs) const
	{
		if (is_null) {
			return !rhs.is_null;	// less than only if RHS not null
		}
		else if (rhs.is_null) {

			return false;			// non-null always greater than null
		}

		else {

			return data < rhs.data;	// neither is null, so compare data
		}
	}

	/// \brief Do less-than comparison against hard-coded SQL null
	///
	/// Always returns false because we can only be greater than or
	/// equal to a SQL null.
	bool operator <(const null_type&) const { return false; }
};


#if !defined(DOXYGEN_IGNORE)
// Doxygen will not generate documentation for this section.


// Specialization the Null template for \c void
template <> class Null<void>
{
public:
	bool is_null;
	typedef void value_type;

	Null() :
	is_null(false)
	{
	}
	
	Null(const null_type&) :
	is_null(true)
	{
	}

	Null& operator =(const null_type&)
	{
		is_null = true;
		return *this;
	}
};

#endif // !defined(DOXYGEN_IGNORE)


/// \brief Inserts null-able data into a C++ stream if it is not
/// actually null.  Otherwise, insert something appropriate for null
/// data.
template <class Type, class Behavior>
inline std::ostream& operator <<(std::ostream& o,
		const Null<Type, Behavior>& n)
{
	if (n.is_null)
		return Behavior::null_ostr(o);
	else
		return o << n.data;
}

} // end namespace mysqlpp

#endif
|
|
<
<
<
|

<
|
|
|
|



















<
|
|
|

<
|

|

<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
|
|
<
|
>
|
<
<
<
<
<
<
<
|
|
<
<
<
<
<
<
<
|
|
<
<
<
>
>
>
|
<
|
<
|
|
<
<

<
<
<
<
<
<
<
<
|
<
<
|
|
|
<
<
<
<
<
<
|
<
<
<
<
<
<
<

>
|
<
<
|
<
<
<
|

<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
|
|
<
>
|
>
>
>
|
<
<
<
|
>
>
>
|
<
<
<
|
<
<
<
<
<
<
<
|
>
|

<
<
<
<
<
<
<
<
<
<
|
<
|
<
<
<
<
<
|
<
<
<
<
<
|
<
|
<
<
<
<
<
<
<
<
<
>
|
|
|
|
>
>
>
|
|
<

|
|
|
|
|
|
>
|
<
>
|
|
<
|
|
|
|
<
<
<
<
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
|
<
<
<
<

>
|
<
<
|
<
|
>
>
|
|
<
>
|
<
<
>
|
<
<
<
<
<
<
>
|
|
>
|
>
|
|
<
|
<
<
<
<
<
<
|
|
<
<
>
|
<
<
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
|
|
<

<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
1
2



3
4

5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27

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
56






57







58
59
60


61



62
63

























64
65

66
67
68
69
70
71



72
73
74
75
76



77







78
79
80
81










82

83





84





85

86









87
88
89
90
91
92
93
94
95
96

97
98
99
100
101
102
103
104
105

106
107
108

109
110
111
112




113

















114




115
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

144



















/***********************************************************************
 ssqls6.cpp - Example showing how to insert a collection row using the 



 Specialized SQL Structures feature of MySQL++ and Query::insertfrom().


 Copyright (c) 1998 by Kevin Atkinson, (c) 1999-2001 by MySQL AB,
 (c) 2004-2009 by Educational Technology Resources, Inc., (c) 2008 by 
 AboveNet, Inc.  Others may also hold copyrights on code in this file.  
 See the CREDITS file in the top directory of the distribution for details.

 This file is part of MySQL++.

 MySQL++ is free software; you can redistribute it and/or modify it
 under the terms of the GNU Lesser General Public License as published
 by the Free Software Foundation; either version 2.1 of the License, or
 (at your option) any later version.

 MySQL++ is distributed in the hope that it will be useful, but WITHOUT
 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
 License for more details.

 You should have received a copy of the GNU Lesser General Public
 License along with MySQL++; if not, write to the Free Software
 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
 USA
***********************************************************************/


#include "cmdline.h"
#include "printdata.h"
#include "stock.h"


#include <fstream>

using namespace std;

































// Breaks a given text line of tab-separated fields up into a list of

// strings.
static size_t
tokenize_line(const string& line, vector<mysqlpp::String>& strings)







{
	string field;







	strings.clear();




	istringstream iss(line);
	while (getline(iss, field, '\t')) {
		strings.push_back(mysqlpp::String(field));
	}



	return strings.size();
}














// Reads a tab-delimited text file, returning the data found therein
// as a vector of stock SSQLS objects.
static bool






read_stock_items(const char* filename, vector<stock>& stock_vector)







{
	ifstream input(filename);
	if (!input) {


		cerr << "Error opening input file '" << filename << "'" << endl;



		return false;
	}


























	string line;

	vector<mysqlpp::String> strings;
	while (getline(input, line)) {
		if (tokenize_line(line, strings) == 6) {
			stock_vector.push_back(stock(string(strings[0]), strings[1],
					strings[2], strings[3], strings[4], strings[5]));
		}



		else {
			cerr << "Error parsing input line (doesn't have 6 fields) " << 
					"in file '" << filename << "'" << endl;
			cerr << "invalid line: '" << line << "'" << endl;
		}



	}








	return true;
}













int





main(int argc, char *argv[])





{

	// Get database access parameters from command line









	mysqlpp::examples::CommandLine cmdline(argc, argv);
	if (!cmdline) {
		return 1;
	}

	// Read in a tab-delimited file of stock data
	vector<stock> stock_vector;
	if (!read_stock_items("examples/stock.txt", stock_vector)) {
		return 1;
	}


	try {
		// Establish the connection to the database server.
		mysqlpp::Connection con(mysqlpp::examples::db_name,
				cmdline.server(), cmdline.user(), cmdline.pass());

		// Clear all existing rows from stock table, as we're about to
		// insert a bunch of new ones, and we want a clean slate.
		mysqlpp::Query query = con.query();

		query.exec("DELETE FROM stock");

		// Insert data read from the CSV file, allowing up to 1000

		// characters per packet.  We're using a small size in this
		// example just to force multiple inserts.  In a real program,
		// you'd want to use larger packets, for greater efficiency.
		mysqlpp::Query::MaxPacketInsertPolicy<> insert_policy(1000);




		query.insertfrom(stock_vector.begin(), stock_vector.end(),

















				insert_policy);





		// Retrieve and print out the new table contents.
		print_stock_table(query);


	}

	catch (const mysqlpp::BadQuery& er) {
		// Handle any query errors
		cerr << "Query error: " << er.what() << endl;
		return -1;
	}

	catch (const mysqlpp::BadConversion& er) {
		// Handle bad conversions


		cerr << "Conversion error: " << er.what() << endl <<
				"\tretrieved data size: " << er.retrieved <<






				", actual size: " << er.actual_size << endl;
		return -1;
	}
	catch (const mysqlpp::BadInsertPolicy& er) {
		// Handle bad conversions
		cerr << "InsertPolicy error: " << er.what() << endl;
		return -1;
	}

	catch (const mysqlpp::Exception& er) {






		// Catch-all for any other MySQL++ exceptions
		cerr << "Error: " << er.what() << endl;


		return -1;
	}




















	return 0;
}





















Changes to lib/options.h.


1
2
3
4

5

6
7
8
9
10
11
12
13
14


15
16
17
18
19
20
21

22




23
24
25
26


27



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
56
57
58
59
60
61
62

63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81




82






83


84
85
86



87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104

105
106

107
108
109
110
111
112
113
114
115
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
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
191



192
193

194
195
196



197
198



199
200


201

202
203
204



205
206

207
208
209


210
211
212
213
214



215
216
217

218
219
220
221
222
223
224

225
226
227




228
229
230

231
232
233
234


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
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
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
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
372




373



374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392


393
394
395
396
397
398
399

400
401
402

403



404
405
406



407



408
409
410
411
412


413

414
415
416
417
418
419
420
421
422
423
424
425
426
427

428
429
430
431
432
433
434




435
436
437
438
439



440

441
442

443
444
445
446
447
448
449

450
451
452
453
454
455
456
457
458
459
460
461
462
463
464

465


466
467
468
469
470
471

472
473

474

475
476
477
478
479
480


481
482
483
484
485
486
487
488
489


490
491
492
493
494

495
496
497


/// \file options.h
/// \brief Declares the Option class hierarchy, used to implement
/// connection options in Connection and DBDriver classes.
///

/// This is tied closely enough to DBDriver that there's a pure-OO

/// argument that it should be declared as protected or private members
/// within DBDriver.  We do it outside DBDriver because there's so much
/// of it.  It'd overwhelm everything else that's going on in that class
/// totally out of proprortion to the importance of options.

/***********************************************************************
 Copyright (c) 2007-2009 by Educational Technology Resources, Inc.
 Others may also hold copyrights on code in this file.  See the
 CREDITS file in the top directory of the distribution for details.



 This file is part of MySQL++.

 MySQL++ is free software; you can redistribute it and/or modify it
 under the terms of the GNU Lesser General Public License as published
 by the Free Software Foundation; either version 2.1 of the License, or
 (at your option) any later version.






 MySQL++ is distributed in the hope that it will be useful, but WITHOUT
 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
 License for more details.






 You should have received a copy of the GNU Lesser General Public
 License along with MySQL++; if not, write to the Free Software
 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
 USA
***********************************************************************/



#if !defined(MYSQLPP_OPTIONS_H)
#define MYSQLPP_OPTIONS_H

#include "common.h"

#include <deque>
#include <string>









namespace mysqlpp {

#if !defined(DOXYGEN_IGNORE)
class DBDriver;
#endif



////////////////////////////////////////////////////////////////////////
// Classes


/// \brief Define abstract interface for all *Option subclasses.
///
/// This is the base class for the mid-level interface classes that take
/// arguments, plus the direct base for options that take no arguments.
class MYSQLPP_EXPORT Option
{
public:
	/// \brief Types of option setting errors we can diagnose
	enum Error {
		err_NONE,		///< option was set successfully

		err_api_limit,	///< option not supported by underlying C API
		err_api_reject,	///< underlying C API returned error when setting option
		err_connected,	///< can't set the given option while connected
		err_disconnected///< can only set the given option while connected
	};
	
	virtual ~Option() { }					///< Destroy object
	virtual Error set(DBDriver* dbd) = 0;	///< Apply option
};


/// \brief Define abstract interface for all *Options that take a
/// lone scalar as an argument.
template <typename T>
class MYSQLPP_EXPORT DataOption : public Option
{
public:
	typedef T ArgType;						///< Alias for template param





protected:






	DataOption(const T& arg) : arg_(arg) { }///< Construct object


	T arg_;									///< The argument value
};




typedef DataOption<unsigned> IntegerOption;		///< Option w/ int argument
typedef DataOption<bool> BooleanOption;			///< Option w/ bool argument
typedef DataOption<std::string> StringOption;	///< Option w/ string argument


/// \brief Enable data compression on the connection
class MYSQLPP_EXPORT CompressOption : public Option
{
#if !defined(DOXYGEN_IGNORE)
public:
	CompressOption() : Option() { }

private:
	Error set(DBDriver* dbd);
#endif
};



/// \brief Change Connection::connect() default timeout
class MYSQLPP_EXPORT ConnectTimeoutOption : public IntegerOption

{
#if !defined(DOXYGEN_IGNORE)
public:
	ConnectTimeoutOption(ArgType arg) : IntegerOption(arg) { }

private:
	Error set(DBDriver* dbd);
#endif
};


/// \brief Make Query::affected_rows() return number of matched rows
///
/// Default is to return number of \b changed rows.
class MYSQLPP_EXPORT FoundRowsOption : public BooleanOption
{
#if !defined(DOXYGEN_IGNORE)


public:



	FoundRowsOption(ArgType arg) : BooleanOption(arg) { }

private:
	Error set(DBDriver* dbd);
#endif
};


/// \brief Allow C API to guess what kind of connection to use
///
/// This is the default.  The option exists to override
/// UseEmbeddedConnectionOption and UseEmbeddedConnectionOption.
class MYSQLPP_EXPORT GuessConnectionOption : public Option
{
#if !defined(DOXYGEN_IGNORE)
public:
	GuessConnectionOption() : Option() { }



private:
	Error set(DBDriver* dbd);
#endif
};


/// \brief Allow spaces after function names in queries
class MYSQLPP_EXPORT IgnoreSpaceOption : public BooleanOption
{
#if !defined(DOXYGEN_IGNORE)
public:
	IgnoreSpaceOption(ArgType arg) : BooleanOption(arg) { }


private:
	Error set(DBDriver* dbd);
#endif
};



/// \brief Give SQL executed on connect
class MYSQLPP_EXPORT InitCommandOption : public StringOption
{
#if !defined(DOXYGEN_IGNORE)
public:
	InitCommandOption(ArgType arg) : StringOption(arg) { }

private:
	Error set(DBDriver* dbd);
#endif
};


/// \brief Assert that this is an interactive program
///
/// Affects connection timeouts.
class MYSQLPP_EXPORT InteractiveOption : public BooleanOption
{
#if !defined(DOXYGEN_IGNORE)
public:
	InteractiveOption(ArgType arg) : BooleanOption(arg) { }

private:
	Error set(DBDriver* dbd);
#endif

};




/// \brief Enable LOAD DATA LOCAL statement
class MYSQLPP_EXPORT LocalFilesOption : public BooleanOption



{
#if !defined(DOXYGEN_IGNORE)

public:
	LocalFilesOption(ArgType arg) : BooleanOption(arg) { }




private:
	Error set(DBDriver* dbd);



#endif
};





/// \brief Enable LOAD LOCAL INFILE statement
class MYSQLPP_EXPORT LocalInfileOption : public IntegerOption



{
#if !defined(DOXYGEN_IGNORE)

public:
	LocalInfileOption(ArgType arg) : IntegerOption(arg) { }



private:
	Error set(DBDriver* dbd);
#endif
};





/// \brief Enable multiple result sets in a reply
class MYSQLPP_EXPORT MultiResultsOption : public BooleanOption

{
#if !defined(DOXYGEN_IGNORE)
public:
	MultiResultsOption(ArgType arg) : BooleanOption(arg) { }

private:
	Error set(DBDriver* dbd);

#endif
};






/// \brief Enable multiple queries in a request to the server
class MYSQLPP_EXPORT MultiStatementsOption : public BooleanOption

{
#if !defined(DOXYGEN_IGNORE)
public:
	MultiStatementsOption(ArgType arg) : BooleanOption(arg) { }



private:
	Error set(DBDriver* dbd);
#endif
};






/// \brief Suggest use of named pipes
class MYSQLPP_EXPORT NamedPipeOption : public Option


{
#if !defined(DOXYGEN_IGNORE)



public:
	NamedPipeOption() : Option() { }




private:
	Error set(DBDriver* dbd);
#endif
};




/// \brief Disable db.tbl.col syntax in queries
class MYSQLPP_EXPORT NoSchemaOption : public BooleanOption


{
#if !defined(DOXYGEN_IGNORE)
public:
	NoSchemaOption(ArgType arg) : BooleanOption(arg) { }



private:
	Error set(DBDriver* dbd);
#endif
};




#if MYSQL_VERSION_ID > 40000		// only in 4.0 +
/// \brief Set type of protocol to use
class MYSQLPP_EXPORT ProtocolOption : public IntegerOption
{
#if !defined(DOXYGEN_IGNORE)
public:
	ProtocolOption(ArgType arg) : IntegerOption(arg) { }

private:
	Error set(DBDriver* dbd);

#endif
};
#endif




/// \brief Override use of my.cnf
class MYSQLPP_EXPORT ReadDefaultFileOption : public StringOption


{
#if !defined(DOXYGEN_IGNORE)
public:
	ReadDefaultFileOption(ArgType arg) : StringOption(arg) { }

private:
	Error set(DBDriver* dbd);
#endif
};





/// \brief Override use of my.cnf
class MYSQLPP_EXPORT ReadDefaultGroupOption : public StringOption
{
#if !defined(DOXYGEN_IGNORE)
public:
	ReadDefaultGroupOption(ArgType arg) : StringOption(arg) { }

private:
	Error set(DBDriver* dbd);
#endif
};


/// \brief Set timeout for IPC data reads
class MYSQLPP_EXPORT ReadTimeoutOption : public IntegerOption
{
#if !defined(DOXYGEN_IGNORE)
public:
	ReadTimeoutOption(ArgType arg) : IntegerOption(arg) { }


private:
	Error set(DBDriver* dbd);
#endif
};






/// \brief Enable automatic reconnection to server
class MYSQLPP_EXPORT ReconnectOption : public BooleanOption
{
#if !defined(DOXYGEN_IGNORE)
public:
	ReconnectOption(ArgType arg) : BooleanOption(arg) { }


private:

	Error set(DBDriver* dbd);
#endif
};



/// \brief Set reporting of data truncation errors
class MYSQLPP_EXPORT ReportDataTruncationOption : public BooleanOption
{

#if !defined(DOXYGEN_IGNORE)
public:
	ReportDataTruncationOption(ArgType arg) : BooleanOption(arg) { }

private:
	Error set(DBDriver* dbd);
#endif
};




/// \brief Enforce use of secure authentication, refusing connection if

/// not available
class MYSQLPP_EXPORT SecureAuthOption : public BooleanOption
{
#if !defined(DOXYGEN_IGNORE)
public:
	SecureAuthOption(ArgType arg) : BooleanOption(arg) { }

private:
	Error set(DBDriver* dbd);

#endif
};



/// \brief Give path to charset definition files
class MYSQLPP_EXPORT SetCharsetDirOption : public StringOption

{
#if !defined(DOXYGEN_IGNORE)
public:
	SetCharsetDirOption(ArgType arg) : StringOption(arg) { }




private:
	Error set(DBDriver* dbd);
#endif
};









/// \brief Give name of default charset
class MYSQLPP_EXPORT SetCharsetNameOption : public StringOption
{
#if !defined(DOXYGEN_IGNORE)
public:
	SetCharsetNameOption(ArgType arg) : StringOption(arg) { }

private:
	Error set(DBDriver* dbd);
#endif
};


/// \brief Fake client IP address when connecting to embedded server
class MYSQLPP_EXPORT SetClientIpOption : public StringOption
{
#if !defined(DOXYGEN_IGNORE)
public:


	SetClientIpOption(ArgType arg) : StringOption(arg) { }

private:
	Error set(DBDriver* dbd);
#endif
};



/// \brief Set name of shmem segment for IPC
class MYSQLPP_EXPORT SharedMemoryBaseNameOption : public StringOption

{



#if !defined(DOXYGEN_IGNORE)
public:
	SharedMemoryBaseNameOption(ArgType arg) : StringOption(arg) { }







private:
	Error set(DBDriver* dbd);
#endif
};





/// \brief Specialized option for handling SSL parameters.
class MYSQLPP_EXPORT SslOption : public Option
{
public:
	/// \brief Create a set of SSL connection option parameters
	///
	/// \param key the pathname to the key file
	/// \param cert the pathname to the certificate file
	/// \param ca the pathname to the certificate authority file
	/// \param capath directory that contains trusted SSL CA
	///        certificates in pem format.
	/// \param cipher list of allowable ciphers to use
	///
	/// This option replaces \c Connection::enable_ssl() from MySQL++

	/// version 2.  Now you can set this connection option just like any
	/// other.
	SslOption(const char* key = 0, const char* cert = 0,
			const char* ca = 0, const char* capath = 0,
			const char* cipher = 0)
	{
		if (key)	key_.assign(key);




		if (cert)	cert_.assign(cert);
		if (ca)		ca_.assign(ca);
		if (capath)	capath_.assign(capath);
		if (cipher)	cipher_.assign(cipher);
	}





private:
	std::string key_, cert_, ca_, capath_, cipher_;

	Error set(DBDriver* dbd);
};


/// \brief Connect to embedded  server in preference to remote server
class MYSQLPP_EXPORT UseEmbeddedConnectionOption : public Option
{

#if !defined(DOXYGEN_IGNORE)
public:
	UseEmbeddedConnectionOption() : Option() { }

private:
	Error set(DBDriver* dbd);
#endif
};


/// \brief Connect to remote server in preference to embedded server
class MYSQLPP_EXPORT UseRemoteConnectionOption : public Option
{
#if !defined(DOXYGEN_IGNORE)
public:

	UseRemoteConnectionOption() : Option() { }



private:
	Error set(DBDriver* dbd);
#endif
};



/// \brief Set timeout for IPC data reads

class MYSQLPP_EXPORT WriteTimeoutOption : public IntegerOption

{
#if !defined(DOXYGEN_IGNORE)
public:
	WriteTimeoutOption(ArgType arg) : IntegerOption(arg) { }

private:


	Error set(DBDriver* dbd);
#endif
};


////////////////////////////////////////////////////////////////////////
// Typedefs

/// \brief The data type of the list of connection options


typedef std::deque<Option*> OptionList;

/// \brief Primary iterator type into List
typedef OptionList::const_iterator OptionListIt;


} // end namespace mysqlpp

#endif // !defined(MYSQLPP_OPTIONS_H)

>
|
|
<
<
>
|
>
|
<
|
<

<
<
<
<
>
>

|

<
<
<
<
>

>
>
>
>
|
<
<
<
>
>

>
>
>
|
<
<
<
<

>
>
|
|
|
<
|
|
<

>
>
>
>
>
>
>

<

<
|
<
|
>

<
<
>

<
<
<
|
<
|
<
<
<
<
>
<
<
<
<
<
|
<
<
<
|
|
<
<
<
<
<
|
<
|
>
>
>
>
|
>
>
>
>
>
>
|
>
>
|
<
|
>
>
>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<

|
>
|
|
>
|
<
|
|
|
|
<
<
<
|
|
<
<
<
<
|
<
>
>
|
>
>
>
<

<
<
<
<
|
|
<
<
<
<
<
|
<
|
<
|
>
>
|
<
<
<
|
|
<
<
|
<
<
<
>

|
|
<
|

>

|
|
|
|
|
<

<
<
<
<
|
|
|
<
<
<
|
<
|
<
|
<
<
|
>
|

>
>

<
<
>
>
>
|
|
>
|
<

>
>
>
|
|
>
>
>
|
<
>
>

>

<
<
>
>
>
|
<
>
|
<

>
>
|
<
<
<

>
>
>

<
<
>
|
<
<
|
|
<
<
>
|
<

>
>
>
>

<
|
>
|
<
|
<
>
>

<
<
<
<

>
>
>
>

<
<
>
>
|
<
>
>
>
|
<

>
>
>
|
|
<
<

>
>

|
|
>
>
|
<
<
|
>
>

<
<
|
<
|
>
>

<
|
|
|
|
|
<

<
|
>
|
<
<

>
>

<
|
>
>
|
<
<
|

|
|
|
<
|
>

>
>
|
<
|
<
|
|

|
|
|
<
|
|
<
<
|
<
<
|
>

<
|
<
<

>
>
>
>

|
|
|
|
<
<

>
|
>
|
|
<
|
|
>
|
|
<
>
|
|
|
|
<
<
<
<

>
>

<
>
|
<
|
<
<
<

|
<
>
|
<

>

<
|
>
|
<
<
<
>
>
>

<
|
<
<
>
>
>
>

>
>
>
|
<
<
|
<
|
<
|
<
|
<
<
|
|
<
<
|
<
<
>
>
|
|
<
<
<
<

>
|
<
<
>
|
>
>
>
|
|
|
>
>
>

>
>
>
|
<
<
<

>
>

>
|
<
|
<
<
<
<
<
|
|
<
|
|
<
>
|
|
<
<
<
|
<
>
>
>
>
<
<
<
<
|
>
>
>

>
|
|
>
|
<

|
|
<
|
>
|
|
<
|
<
<
<
<

|
<
<
|
<
<
>
|
>
>

|
|
|
<
|
>

|
>
|
>
|
<
<
|
|
|
>
>
|
<
<

|
<
<
|
|
>
>
|
|
<
|

>
|
|
<
>
1
2
3


4
5
6
7

8

9




10
11
12
13
14




15
16
17
18
19
20
21



22
23
24
25
26
27
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





56



57
58





59

60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75

76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94

95
96
97
98
99
100
101

102
103
104
105



106
107




108

109
110
111
112
113
114

115




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



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


191
192


193
194


195
196

197
198
199
200
201
202

203
204
205

206

207
208
209




210
211
212
213
214
215


216
217
218

219
220
221
222

223
224
225
226
227
228


229
230
231
232
233
234
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

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

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
372
373
374
375



376
377
378
379
380
381

382





383
384

385
386

387
388
389



390

391
392
393
394




395
396
397
398
399
400
401
402
403
404

405
406
407

408
409
410
411

412




413
414


415


416
417
418
419
420
421
422
423

424
425
426
427
428
429
430
431


432
433
434
435
436
437


438
439


440
441
442
443
444
445

446
447
448
449
450

451
Patches for any of these thoughtfully considered!  See the HACKERS.txt
file for instructions on sending patches.



Any Version
-----------
    o Any time you must hand-roll some SQL code in your program,
      consider whether it could be generalized to a widely-useful

      API feature.






    o Suppress DOS line-ending related diffs from examples/cgi_jpeg
      output when running dtest on Windows.  Check for -D?

    o Need to link statically to connect to MySQL Embedded?





      http://stackoverflow.com/questions/672451/howto-communicate-with-mysql-embedded-server-from-mysql-dll

    o When Bakefile allows, bring examples/vstudio/* into the top-level
      build system.  This will let us generate separate project
      files for each VC++ version we support, let us use MYSQL_WIN_DIR
      variable instead of hard-coded paths, and build against the local
      version of MySQL++ instead of requiring it to be installed first.



      Should probably drop the MFC example project, to avoid requiring
      Visual C++ Professional.

    o Query::storein(slist<T>&) is unusable.  As a template method, it
      must be defined in a header file; we cannot #include config.h from
      a header, thus the proper HAVE macro that would let us define this
      template method is never defined.





      One solution is to create lib/slist.h.in, parameterized by the
      detected slist type name and the header file defining it.  This
      will #include the proper header file, define SList<T>::Type (a
      template typdedef: http://www.gotw.ca/gotw/079.htm), and #define
      MYSQLPP_HAVE_SLIST.  Then Query::storein() can be wrapped by an

      ifdef checking for MYSQLPP_HAVE_SLIST, only defined when the
      configure script found a suitable slist type.


      Also create a default lib/slist.h file, checked into svn as
      lib/slistdef.h and copied to slist.h on tarball creation.  Remove
      this file early in configure script run, so we're forced to
      overwrite its contents with detected values.  Default version
      contains ifdefs for non-autoconf platforms where we know what
      slist definition is available on that platform.  Xcode, for
      instance, will let us use <ext/slist>.




v3.2 Plan: Finish SSQLS v2

--------------------------
    See http://lists.mysql.com/plusplus/6929 for high-level plan.



    o Goal: Restore VC++ 2003 compatibility with SSQLS, lost with v1




    o C++ code generator, from walking DSL parse tree:






      examples/stock.ssqls gives ssqls_stock.h containing:









          class SQLStock : public mysqlpp::SsqlsBase
          {





          public:

              SQLStock(Connection* conn = 0); // default ctor
              SQLStock(const SQLStock& other);
              SQLStock(const mysqlpp::Row& row,
                      Connection* conn = 0); // full init from query
              SQLStock(mysqlpp::sql_bigint key1); // exemplar creation
              SQLStock(Connection* conn,
                      mysqlpp::sql_bigint key1) // calls load();
              SQLStock(
                  mysqlpp::sql_bigint f1,
                  mysqlpp::sql_bigint f2,
                  mysqlpp::sql_double f3,
                  mysqlpp::sql_double f4,
                  const mysqlpp::sql_date& f5,
                  const mysqlpp::sql_mediumtext& f6); // full init
              SQLStock(Connection* conn,
                  mysqlpp::sql_bigint f2,

                  mysqlpp::sql_double f3,
                  mysqlpp::sql_double f4,
                  const mysqlpp::sql_date& f5,
                  const mysqlpp::sql_mediumtext& f6); // calls create()
              SQLStock(Connection* conn,
                  mysqlpp::sql_bigint f1,
                  mysqlpp::sql_bigint f2,
                  mysqlpp::sql_double f3,
                  mysqlpp::sql_double f4,
                  const mysqlpp::sql_date& f5,
                  const mysqlpp::sql_mediumtext& f6); // calls save()

              bool createTable(Connection* conn = 0) const;
              const char* getTableName() const
                      { return class_table_name_ || table(); }
              void setTableName(const char* name)
                      { instance_table(name); }
              static void setTableName(const char* name)
                      { class_table_name_ = name; }


              std::ostream& equal_list(std::ostream& os) const;
              std::ostream& json(std::ostream& os) const;
              std::ostream& name_list(std::ostream& os) const;
              std::ostream& value_list(std::ostream& os) const;
              std::ostream& xml(std::ostream& os) const;


              mysqlpp::sql_bigint getId() const;
              mysqlpp::sql_bigint getNum() const;
              mysqlpp::sql_double getWeight() const;
              mysqlpp::sql_double getPrice() const;



              const mysqlpp::sql_date& getSdate() const;
              const mysqlpp::sql_mediumtext& getDescription() const;






              void setId(mysqlpp::sql_bigint value);
              void setNum(mysqlpp::sql_bigint value);
              void setWeight(mysqlpp::sql_double value);
              void setPrice(mysqlpp::sql_double value);
              void setSdate(const mysqlpp::sql_date& value);
              void setDescripion(const mysqlpp::sql_mediumtext& value);






              bool operator<(const SQLStock& rhs) const;
              SQLStock& operator=(const SQLStock& rhs);







          protected:

              mysqlpp::sql_bigint id_;
              mysqlpp::sql_bigint num_;
              mysqlpp::sql_double weight_;
              mysqlpp::sql_double price_;



              mysqlpp::sql_date sdate_;
              mysqlpp::sql_mediumtext description_;






              std::bitset<6> set_fields_;

          private:
              static const char* class_table_name_;

          };

      ...and ssqls_stock.cc, containing implementation for same.

    o Ensure we're using case-insensitive SQL column to C++ field name
      matching.  Column names aren't case-sensitive in SQL.

    o SQL table updater/builder, -T option, taking .ssqls and
      creating or updating the DB table to match.






    o If using accessors, generate "std::bitset<num_fields> is_set_",
      and set the appropriate bit when calling each setFoo() so we
      can intuit which fields were set.  Probably also need an enum:





          enum FieldIndices {

              id_field_index_,


              num_field_index_,
              ...
          };

      This will allow Query::select(), for instance, to figure out that
      we want it to select by a non-key field, returning all matches.



    o Define operator<< for SSQLS and a set of manipulators which
      govern whether the operator calls equal_list(), json(),
      name_list(), value_list(), or xml() to do the actual insertion.

    o Define operator<< for sequence_container<SsqlsBase> and similar
      for associative containers.  Give mysql(1)-like ASCII grid or
      some other table format.


    o Define operator>> for SSQLS, taking XML as input, in the form
      emitted via xml().  expat uses the new BSD license, so maybe
      we can just drop it in the tree, with an option to use the
      platform expat on autoconf systems.

    o MySQL table metadata to SSQLSv2 data structure translator.
      (-s, -u, -p and -t flag support.)  Add this to dtest, extracting
      stock.ssqls definition from DB.


    o Replace Query's template methods taking SSQLSes with concrete
      methods taking const SsqlsBase&.

    o Create Query::remove(const SsqlsBase&)



    o Try to remove of 'explicit' from Date, DateTime and Time
      ctors taking stringish types.  (Can't do it for real until v4,
      but we can lay the ground work here.)


    o Auto-create() ctor: if there is an auto_increment field,
      populate it on query success.


    o Detect ctor conflicts corresponding to sql_create_N(N, N...)
      in SSQLSv1.  ssqlsxlat can be smart enough to just not emit
      duplicate ctors.




    o Special case of ctor suppression: if the number of key fields
      equals the total number of fields, you get an auto-load() ctor,
      not auto-update().



    o Replace CREATE TABLE SQL in resetdb with create_table() calls.



    o Option to use integer indices into Row when populating?  Only
      bother if it gives a speed advantage we can actually see,


      because it removes all the dynamic typing advantages we got
      with the change to field name indices in v3.0.


    o Try to add Query::storein(container, ssqls), which generates
      SELECT * from {ssqls.table()} and stores the result.  May not be
      possible due to existing overloads, but try.  If it works, use
      this form in the userman Overview section, saving one LOC.


    o Convert SSQLS v1 examples to v2.  SSQLS v2 isn't done until
      there's a straightformward conversion path for all examples.


    o Add #warning to generated ssqls.h saying that you should now use

      SSQLS v2.  Wrap it in a check for MYSQLPP_ALLOW_SSQLS_V1,
      so people can disable the warning.






v3.3 Tentative Plan
-------------------
    o Add Query::storein<Container, T>(container), getting table
      name from container::value_type.table() instead.



    o Define operator<< for Fields, Row, StoreQueryResult, etc., giving
      CSV format.


    o Remove libexcommon.  Between above and SSQLSv2, we should have
      everything we need to get equivalent output without special
      purpose code.  There should be no ad hoc data dumping code in
      the examples.


    o Bring back mandatory quoting for manipulators?  If someone says
      os << mysqlpp::escape << foo; do they not really really mean
      escape foo?  Automatic quoting and escaping is different.  See

      http://lists.mysql.com/plusplus/7999



    o Configure script should try to get MySQL C API directories
      from mysql_config.

    o If pkg-config is available, register ourselves with it using
      information discovered by configure.  Also, write out a
      mysql++-config script, which either wraps pkg-config or
      reinvents it, poorly, for systems that don't have it.



    o Add String::operator==(const mysqlpp::null_type&).  Needed to
      allow comparison of row[x] returns to SQL null.  Change one of
      the examples to show it?



    o Memory "leak" and C API library init fixes:

    
      - Add DBDriver::library_begin() and library_end(), wrapping
        similarly named functions in the C API.


      - Create Process class, which you create at the top of main()
        on the stack, purely to call these automatically.

      - Update userman to recommend creating Process object in
        ConnectionPool derivatives, instead.



      - Create Thread class to call existing DBDriver::thread_start()
        and thread_end(), similar to Process, created on the stack
        of the thread entry function.



      - Move memory leak FAQ into userman, rewriting it to cover
        all this.


    o mysqlpp::execute manipulator.  Immediately executes built
      query string.  Works best with exceptions, as that's the only way
      to detect failures.



    o Chris Frey's packarray class

    o Create adaptors for std::bitset, for storing binary data in a
      MySQL table.  Make two options available, one for storing the
      return from bitset::to_ulong() in an UNSIGNED INTEGER column,

      and another for storing a larger set of bits in a more flexible
      way, perhaps as a BLOB.

    o Create a backtick manipulator for use by field_list() in row.h
      and ssqls.h.  These currently use do_nothing0, but that prevents
      use of SQL reserved words as identifiers.



    o Has experience with new thread awareness changed our mind on
      atomic inc/dec of reference counts in RefCounted*?

    o Create a fixed-point data type for use with SQL's DECIMAL and
      related types.  Right now, sql_decimal is a typedef for double,
      so you lose accuracy in the fractional part.  Don't forget to

      include an "is_null" flag to cope with conversion from infinite
      or NaN float values; that's how MySQL stores these.





    o Optional checked conversions in String for numerics: throw
      BadConversion on range overflow?


    o Add Query::storein_if(), mirroring store_if()



    o Add a method to mysqlpp::String to return a widened version of the
      string.  Probably make return type templatized so we can return
      wstring, C++/CLI native strings, etc.  Then convert examples that
      do this conversion to use this new mechanism.

    o Try to add operator std::string to String.  If it doesn't work,
      explain why not in the userman, and in Row::operator[] refman.
      
    o Wrap LOAD DATA INFILE:



      bool Query::load_file(
          const char* path,
          bool local_path,
          const char* table,
          const char* field_terminator = 0,   // default \t

          const char* field_encloser = 0,     // default none
          const char* field_escape = 0,       // default \
          const char* line_terminator = 0,    // \n on *ix, \r\n on Windows
          const char* line_starter = 0,       // default none
          const char* character_set = 0,      // default UTF-8

          const char* comment_prefix = 0,     // ignore no lines
          bool replace_existing = false,
          bool ignore_duplicates = false,
          bool low_priority = false,
          int skip_lines = 0);





    o Wrappers for above: load_local_tab_file(), load_local_csv_file(),
      load_remote_*()...


    o Query::save_file() interfaces, wrapping SELECT ... INTO FILE,
      modeled on above.






v4.0 or Later

-------------
    o Database independence:


      - Use libdbi or similar?  http://libdbi.sf.net/


      - Make DBDriver class purely abstract; move its entire functional
        contents to new MysqlDriver.




      - Must create at least two other DBDriver subclasses to
        ensure base class is reusable before releasing v4.0.
        PostgresDriver and SqlLiteDriver?


      - Templatize all classes that use DBDriver interface with the


        DB driver type.  This lets you specify the driver type to use
        with a Connection and all its children without modifying the
        existing method parameter lists.  This also lets us worry less
        about C API types, as they can be hidden away behind typedefs:

        class MysqlDriver : public DBDriver { ...
           typedef MYSQL_ROW row_type;
           ...
        }




        template <class DBD = MysqlDriver>

        class Connection ... { ...

           Query<DBD> query();


           ...
        }





        template <class DBD = MysqlDriver>
        class UseQueryResult { ...
            DBD::row_type fetch_raw_row();
        }





      - Tricky bits:
    


        - Initializing result set objects.

        - type_info module.  Extremely closely tied to MySQL C API
          right now.  Will probably have to turn it into a parallel
          class hierarchy to DBDriver, or fold it in with same.

        - Building MySQL++ on systems without autoconf.  How to
          specify what DB engines are available?  Probably default to
          supporting MySQL only, and let people turn things on manually
          as they need them.  Or, maybe make them use Bakefile so they
          can fiddle with the options if they want something atypical.

    o Fork mysqlpp::String into mysqlpp::Blob, which differs only in
      that it knows that it should be automatically quoted and escaped
      when inserted into a SQL query.  Could do this in 3.x, but it's a
      pretty serious API breakage.




    o Some sort of support for prepared statements.  Can we hijack
      the template query mechanism?

    o If SSQLSv2 does use a common base class, change Query template
      methods taking SSQLS into concrete methods taking SsqlsBase&.







    o Make Query::insert(), replace() and update() execute their
      queries immediately.  Requires an ABI break, because they'll

      have to return SimpleResult.


    o Switch Query's safe bool to overload basic_ios<>::operator
      void*() instead.  We create an ambiguous conversion in bool
      context with some C++ standard libraries otherwise.





    o Templatize mysqlpp::String on value_type so it can be used to
      hold wide characters.  Then the method that converts UTF-8 to the
      platform's best wide character type can just return a different
      variant of mysqlpp::String.





    o Add wrapper functions to Null<> like length() that call the
      corresponding function on data member, if present, to make it
      more transparent.  At minimum, mirror the std::string API.

    o Transaction class should check an "in transaction" flag on
      Connection (or DBDriver) before sending BEGIN, defaulting to
      false.  If set, the Transaction object does nothing.  If not
      set, set it and send the query.  This prevents it from trying
      to set up nested queries, which MySQL doesn't support.


    o Remove throw-spec for std::out_of_range from SQLTypeAdapter::at().
      It no longer throws this, and throw-specs are passee' anyway.


    o Store failed query string in BadQuery exception object, to make
      logging and debugging easier.  One could have a try block wrapping
      many queries, and be able to recover the failed query string from

      the exception object, instead of somehow keeping track yourself.





      Patch: http://lists.mysql.com/plusplus/8374


 


    o Query and SQLStream could have a common base class that would
      allow the stream manipulator functions to catch and modify
      strings based on only one dynamic_cast instead of requiring
      two as it does since the addition of the SQLStream class.

    o Make internal call chain steps like Query::execute(SQLQueryParms&)
      protected?  No good reason for end users to call it, and making
      it part of the public API causes people to try calling it, and

      discovering that it's not a very elegant interface, compared to
      the ones taking SQLStrings.

    o SQL time type allows +/- 839 hours of range.  v3.0 code doesn't
      cope with negative times, and if we change it to use signed
      integers, we'll still only get +/-127 hours instead of +255.
      Need to switch the hour field to a short to get the full range.



    o Create a thread-safe message queue for separating DB access and
      data use into multiple threads.  Something like ConnectionPool,
      optional and with no ties to the internals of MySQL++.  There
      could be an adapter between one end of the queue and a Connection
      object, which creates Queries to handle standardized messages,
      delivering the results back to the queue.



    o Get rid of two-step create in DBDriver, requiring a connection to


      be established in ctor for object to be valid?  RAII.  The
      DB-specific functions that don't require a connection can be
      static methods.  Tricky bit: a failed Connection::connect() call
      will likely be followed by an indirect call to DBDriver::err*().
      Does Connection cache the error value and message?  If we can pull
      this off, we can drop the DBDriver::is_connected_ flag and change

      Connection::connected() to "return driver_ != 0".

    o Add STL-like custom Allocator template parameters to memory-hungry
      classes like Row?  Useful in apps that process lots of data over
      long periods, causing heap fragmentation with the default C++

      allocator.

Changes to lib/qparms.cpp.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
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

56
57
58
59
60
61
62
63
64

65

66
67
68
69
70
71


72
73
74
75
76
77

78
79

80
81
82
83

/***********************************************************************
 qparms.cpp - Implements the SQLQueryParms class.

 Copyright (c) 1998 by Kevin Atkinson, (c) 1999, 2000 and 2001 by
 MySQL AB, and (c) 2004-2007 by Educational Technology Resources, Inc.
 Others may also hold copyrights on code in this file.  See the CREDITS
 file in the top directory of the distribution for details.

 This file is part of MySQL++.

 MySQL++ is free software; you can redistribute it and/or modify it
 under the terms of the GNU Lesser General Public License as published
 by the Free Software Foundation; either version 2.1 of the License, or
 (at your option) any later version.

 MySQL++ is distributed in the hope that it will be useful, but WITHOUT
 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
 License for more details.

 You should have received a copy of the GNU Lesser General Public
 License along with MySQL++; if not, write to the Free Software
 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
 USA
***********************************************************************/

#include "qparms.h"

#include "query.h"

using namespace std;

namespace mysqlpp {

size_t
SQLQueryParms::escape_string(std::string* ps, const char* original,
		size_t length) const

{
	return parent_ ? parent_->escape_string(ps, original, length) : 0;



}







size_t
SQLQueryParms::escape_string(char* escaped, const char* original,
		size_t length) const
{
	return parent_ ? parent_->escape_string(escaped, original, length) : 0;
}


SQLTypeAdapter&
SQLQueryParms::operator [](const char* str)
{





	if (parent_) {
		return operator [](parent_->parsed_nums_[str]);
	}

	throw ObjectNotInitialized("SQLQueryParms object has no parent!");

}

const SQLTypeAdapter&
SQLQueryParms::operator[] (const char* str) const
{
	if (parent_) {
		return operator [](parent_->parsed_nums_[str]);
	}
	throw ObjectNotInitialized("SQLQueryParms object has no parent!");

}


SQLQueryParms
SQLQueryParms::operator +(const SQLQueryParms& other) const
{
	if (other.size() <= size()) {
		return *this;


	}
	SQLQueryParms New = *this;
	size_t i;
	for (i = size(); i < other.size(); i++) {
		New.push_back(other[i]);
	}


	return New;

}


} // end namespace mysqlpp

<
<
|
<
<
<
<
|
|

|
|
|
|
|
|
|
|
|
|
|
|
|
|
<

<
|
<

<
|
<

|
<
<
>
|
<
>
>
>
|
|
>
>
>
>
>
>
<
<
<
|
<
<
|
>
|
<
|
>
>
>
>
>
|
<
|
>
|
>
|
|
<
|
<
<
<
|
|
>
|
>

<
<
|
|
<
>
>
|
<
<
<
<
|
>

|
>
|
|
|
<
>


1




2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

19

20

21

22

23
24


25
26

27
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



56
57
58
59
60
61


62
63

64
65
66




67
68
69
70
71
72
73
74

75


## This file contains the 'make' rules specific to Visual C++.  The




## ../makemake.bat script prepends this to Makefile.base to create a
## complete Makefile.

# This file is free software; you can redistribute it and/or modify it
# under the terms of the GNU Lesser General Public License as published
# by the Free Software Foundation; either version 2.1 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
# Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public
# License along with MySQL++; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
# USA



MYSQL_DIR=c:\mysql



CYGWIN_MAKE=$(wildcard /bin/cygwin1.dll)


BIN_DIR=debug


EX_BIN_DIR=$(if $(CYGWIN_MAKE),../examples/$(BIN_DIR)/,..\examples\$(BIN_DIR)\)


CXX=cl
CXXFLAGS=/I$(MYSQL_DIR)\include /DMYSQLPP_MAKING_DLL /D_WINDLL /D_UNICODE \
		/G6 /EHsc /nologo /c

LIB_BASE=mysqlpp
LIB_FILE=$(LIB_BASE).dll
IMP_FILE=$(LIB_BASE).lib
VC_LIB_PATH=$(BIN_DIR)\$(LIB_FILE)
PLAT_LIB_PATH=$(if $(CYGWIN_MAKE),\
		$(shell cygpath -u $(VC_LIB_PATH)),\
		$(VC_LIB_PATH))






LD=link
LDFLAGS=/OUT:$(VC_LIB_PATH) /DLL /NOLOGO \
		/LIBPATH:$(MYSQL_DIR)\lib\opt libmysql.lib


ifeq "$(BIN_DIR)" "debug"
	CXXFLAGS += /MDd /Od /D_DEBUG /ZI /Zi
	LDFLAGS += /DEBUG
else
	CXXFLAGS += /MD /O2
endif


vpath %.obj $(BIN_DIR)
vpath %.dll $(BIN_DIR)
vpath %.lib $(BIN_DIR)

EXE=.exe

OBJ=obj




RM=$(if $(CYGWIN_MAKE),rm -rf,del /q)
CP=$(if $(CYGWIN_MAKE),cp,copy)

LOCAL_CLEAN=debug release




.SUFFIXES: .cpp .obj

.cpp.obj:
	$(CXX) $(CXXFLAGS) /Fo$(BIN_DIR)\$@ $<






vc: all

example_setup:
	$(CP) $(PLAT_LIB_PATH) $(EX_BIN_DIR)

$(IMP_FILE):
	$(if $(wildcard $(BIN_DIR)/$(IMP_FILE)),,$(shell $(RM) $(BIN_DIR)/$(LIB_FILE)))

	$(MAKE) $(LIB_FILE)

Changes to lib/qparms.h.

1
2
3
4
5
6
7
8

9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
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
56
57
58

59



60












61
62
63
64
65






66
67
68

69



70
71
72







73
74



75


76
77
78
79
80
81
82


83
84
85

86
87
88




89



90






91

92
93
94
95




96







97




98
99


100
101
102



103
104
105


106
107
108
109


110
111
112


113
114
115



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
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
191







192
193


194
195
196







197
198


199

200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
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
/// \file qparms.h
/// \brief Declares the template query parameter-related stuff.
///
/// The classes defined in this file are used by class Query when it
/// parses a template query: they hold information that it finds in the
/// template, so it can assemble a SQL statement later on demand.

/***********************************************************************

 Copyright (c) 1998 by Kevin Atkinson, (c) 1999-2001 by MySQL AB, and
 (c) 2004-2007 by Educational Technology Resources, Inc.  Others may
 also hold copyrights on code in this file.  See the CREDITS.txt file
 in the top directory of the distribution for details.

 This file is part of MySQL++.

 MySQL++ is free software; you can redistribute it and/or modify it
 under the terms of the GNU Lesser General Public License as published
 by the Free Software Foundation; either version 2.1 of the License, or
 (at your option) any later version.

 MySQL++ is distributed in the hope that it will be useful, but WITHOUT
 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
 License for more details.

 You should have received a copy of the GNU Lesser General Public
 License along with MySQL++; if not, write to the Free Software
 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
 USA
***********************************************************************/

#ifndef MYSQLPP_QPARMS_H
#define MYSQLPP_QPARMS_H


#include "stadapter.h"

#include <vector>

namespace mysqlpp {

#if !defined(DOXYGEN_IGNORE)
// Make Doxygen ignore this



class MYSQLPP_EXPORT Query;
#endif






/// \brief This class holds the parameter values for filling
/// template queries. 
class MYSQLPP_EXPORT SQLQueryParms : public std::vector<SQLTypeAdapter>


{
public:
	/// \brief Abbreviation so some of the declarations below don't
	/// span many lines.
	typedef const SQLTypeAdapter& sta;




	/// \brief Default constructor
	SQLQueryParms() :
	parent_(0),
	processing_(false)

	{



	}












	
	/// \brief Create object
	///
	/// \param p pointer to the query object these parameters are tied
	/// to






	SQLQueryParms(Query* p) :
	parent_(p),
	processing_(false)

	{



	}
	
	/// \brief Returns true if we are bound to a query object.







	///
	/// Basically, this tells you which of the two ctors were called.



	bool bound() { return parent_ != 0; }



	/// \brief Clears the list
	void clear() { erase(begin(), end()); }

	/// \brief Indirect access to Query::escape_string()
	///
	/// \internal Needed by \c operator<<(Manip&, \c const \c T&) where


	/// \c Manip is used on a SQLQueryParms object.  We'd have to make
	/// all these operators friends to give access to our internal Query
	/// object otherwise.

	///
	/// \see Query::escape_string(std::string*, const char*, size_t)
	size_t escape_string(std::string* ps, const char* original = 0,




			size_t length = 0) const;










	/// \brief Indirect access to Query::escape_string()

	///
	/// \see escape_string(std::string*, const char*, size_t)
	/// \see Query::escape_string(const char*, const char*, size_t)
	size_t escape_string(char* escaped, const char* original,




			size_t length) const;












	/// \brief Access element number n
	SQLTypeAdapter& operator [](size_type n)


	{
		if (n >= size()) {
			insert(end(), (n + 1) - size(), "");



		}
		return std::vector<SQLTypeAdapter>::operator [](n);
	}



	/// \brief Access element number n
	const SQLTypeAdapter& operator [](size_type n) const
			{ return std::vector<SQLTypeAdapter>::operator [](n); }


	
	/// \brief Access the value of the element with a key of str.
	SQLTypeAdapter& operator [](const char *str);



	/// \brief Access the value of the element with a key of str.
	const SQLTypeAdapter& operator [](const char *str) const;




	/// \brief Adds an element to the list
	SQLQueryParms& operator <<(const SQLTypeAdapter& str)
	{
		push_back(str);
		return *this;
	}







	/// \brief Adds an element to the list
	SQLQueryParms& operator +=(const SQLTypeAdapter& str)


	{
		push_back(str);
		return *this;


	}

	/// \brief Build a composite of two parameter lists
	///
	/// If this list is (a, b) and \c other is (c, d, e, f, g), then




	/// the returned list will be (a, b, e, f, g).  That is, all of this



	/// list's parameters are in the returned list, plus any from the


	/// other list that are in positions beyond what exist in this list.
	///
	/// If the two lists are the same length or this list is longer than








	/// the \c other list, a copy of this list is returned.


	SQLQueryParms operator +(
			const SQLQueryParms& other) const;











#if !defined(DOXYGEN_IGNORE)
// Doxygen will not generate documentation for this section.

	void set(sta a)
	{




		clear();

		*this << a;
	}
	void set(sta a, sta b)
	{
		clear();






		*this << a << b;
	}

	void set(sta a, sta b, sta c)
	{
		clear();
		*this << a << b << c;



	}
	void set(sta a, sta b, sta c, sta d)
	{
		clear();
		*this << a << b << c << d;
	}

	void set(sta a, sta b, sta c, sta d, sta e)
	{




		clear();
		*this << a << b << c << d << e;


	}
	void set(sta a, sta b, sta c, sta d, sta e, sta f)
	{







		clear();
		*this << a << b << c << d << e << f;


	}
	void set(sta a, sta b, sta c, sta d, sta e, sta f, sta g)
	{








		clear();
		*this << a << b << c << d << e << f << g;


	}
	void set(sta a, sta b, sta c, sta d, sta e, sta f, sta g, sta h)
	{
		clear();
		*this << a << b << c << d << e << f << g << h;
	}
	void set(sta a, sta b, sta c, sta d, sta e, sta f, sta g, sta h, sta i)


	{




		clear();
		*this << a << b << c << d << e << f << g << h << i;


	}
	void set(sta a, sta b, sta c, sta d, sta e, sta f, sta g, sta h, sta i, sta j)
	{







		clear();
		*this << a << b << c << d << e << f << g << h << i << j;


	}
	void set(sta a, sta b, sta c, sta d, sta e, sta f, sta g, sta h, sta i, sta j, sta k)
	{







		clear();
		*this << a << b << c << d << e << f << g << h << i << j << k;


	}

#endif // !defined(DOXYGEN_IGNORE)

	/// \brief Set the template query parameters.
	///
	/// Sets parameter 0 to a, parameter 1 to b, etc. There are
	/// overloaded versions of this function that take anywhere from
	/// one to a dozen parameters.
	void set(sta a, sta b, sta c, sta d, sta e, sta f, sta g,
			sta h, sta i, sta j, sta k, sta l)
	{
		clear();
		*this << a << b << c << d << e << f << g << h << i << j << k << l;
	}

private:
	friend class Query;

	Query* parent_;
	bool processing_;	///< true if we're building a query string
};


/// \brief Used within Query to hold elements for parameterized
/// queries.
///
/// Each element has three parts:
///
/// The concept behind the \c before variable needs a little explaining.
/// When a template query is parsed, each parameter is parsed into one
/// of these SQLParseElement objects, but the non-parameter parts of the
/// template also have to be stored somewhere.  MySQL++ chooses to
/// attach the text leading up to a parameter to that parameter.  So,
/// the \c before string is simply the text copied literally into the
/// finished query before we insert a value for the parameter.
///
/// The \c option character is currently one of 'q', 'Q', 'r', 'R' or
/// ' '.  See the "Template Queries" chapter in the user manual for
/// details.
///
/// The position value (\c num) allows a template query to have its
/// parameters in a different order than in the Query method call.
/// An example of how this can be helpful is in the "Template Queries"
/// chapter of the user manual.

struct SQLParseElement
{
	/// \brief Create object
	///
	/// \param b the 'before' value
	/// \param o the 'option' value
	/// \param n the 'num' value
	SQLParseElement(std::string b, char o, signed char n) :
	before(b),
	option(o),
	num(n)
	{
	}
	
	std::string before;		///< string inserted before the parameter
	char option;			///< the parameter option, or blank if none
	signed char num;		///< the parameter position to use
};

} // end namespace mysqlpp

#endif // !defined(MYSQLPP_QPARMS_H)

<
<
<
<
<
<
<

>
|
|
|
|



















<
|
>

|

<




|
>
>
>
|
|
>
|
>
>
>
>
|
|
<
>
>

<
<
<
<
>
>
>
|
|
|
<
|
>
|
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
|
|
|
<
|
>
>
>
>
>
>
|
|
|
>
|
>
>
>
|
|
|
>
>
>
>
>
>
>
|
|
>
>
>
|
>
>
|
|
<

|
<
<
>
>
|
|
|
>
|
|
<
>
>
>
>
|
>
>
>
|
>
>
>
>
>
>
|
>
|
|
<
<
>
>
>
>
|
>
>
>
>
>
>
>
|
>
>
>
>
|
|
>
>
|
<
<
>
>
>
|
|
|
>
>
|
<
<
|
>
>
|
|
|
>
>
|
<
<
>
>
>
|
<
<
|
<
<
|
>
>
>
>
>
>
|
|
|
>
>
|
<
|
>
>
|

|
<
<
>
>
>
>
|
>
>
>
|
>
>
|
|
<
>
>
>
>
>
>
>
>
|
>
>
|
|
>
>
|
>
>
>
>
>
>
>
>
|
|
>
|
|
>
>
>
>
|
>
|
|
|
|
|
>
>
>
>
>
>
|
|
>
|
|
<
<
>
>
>
|
<
|
<
<
|
>
|
|
>
>
>
>
|
<
>
>
|
|
|
>
>
>
>
>
>
>
|
<
>
>
|
|
|
>
>
>
>
>
>
>
>
|
<
>
>
|
<
|
<
<
|
<
>
>
|
>
>
>
>
|
<
>
>
|
|
|
>
>
>
>
>
>
>
|
<
>
>
|
|
|
>
>
>
>
>
>
>
|
<
>
>
|
>


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

<
<
<







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

26
27
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
56
57

58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79

80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114

115
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


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
191
192
193
194
195
196
197
198
199
200
201

202
203
204
205
206
207


208
209
210
211
212
213
214
215
216
217
218
219
220

221
222
223
224
225
226
227
228
229
230
231
232
233
234
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
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
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
336
337
338

339
340
341
342
343
344
345
346
347
348
349
350
351

352
353
354
355
356
357





























































358










/***********************************************************************
 options.cpp - Implements the Option class hierarchy.

 Copyright (c) 2007 by Educational Technology Resources, Inc.  Others
 may also hold copyrights on code in this file.  See the CREDITS
 file in the top directory of the distribution for details.

 This file is part of MySQL++.

 MySQL++ is free software; you can redistribute it and/or modify it
 under the terms of the GNU Lesser General Public License as published
 by the Free Software Foundation; either version 2.1 of the License, or
 (at your option) any later version.

 MySQL++ is distributed in the hope that it will be useful, but WITHOUT
 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
 License for more details.

 You should have received a copy of the GNU Lesser General Public
 License along with MySQL++; if not, write to the Free Software
 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
 USA
***********************************************************************/


#define MYSQLPP_NOT_HEADER
#include "options.h"

#include "dbdriver.h"



namespace mysqlpp {

#if !defined(DOXYGEN_IGNORE)
// We're hiding all the Option subclass internals from Doxygen.  All the
// upper-level classes are documented fully, and each leaf class itself
// is documented.  It's just the ctors and set() methods we're refusing
// to document over and over again.

Option::Error
CompressOption::set(DBDriver* dbd)
{
	return dbd->connected() ? Option::err_connected :
			dbd->set_option(MYSQL_OPT_COMPRESS) ?
				Option::err_NONE : Option::err_api_reject;
}



Option::Error
ConnectTimeoutOption::set(DBDriver* dbd)
{




	return dbd->connected() ? Option::err_connected :
			dbd->set_option(MYSQL_OPT_CONNECT_TIMEOUT, &arg_) ?
				Option::err_NONE : Option::err_api_reject;
}



Option::Error
FoundRowsOption::set(DBDriver* dbd)
{
	return dbd->connected() ? Option::err_connected :
			dbd->set_option(CLIENT_FOUND_ROWS, arg_) ?
				Option::err_NONE : Option::err_api_reject;
}


Option::Error
GuessConnectionOption::set(DBDriver* dbd)
{
#if MYSQL_VERSION_ID >= 40101
	return dbd->connected() ? Option::err_connected :
			dbd->set_option(MYSQL_OPT_GUESS_CONNECTION) ?
				Option::err_NONE : Option::err_api_reject;
#else
	return Option::err_api_limit;
#endif
}



Option::Error
IgnoreSpaceOption::set(DBDriver* dbd)
{
	return dbd->connected() ? Option::err_connected :
			dbd->set_option(CLIENT_IGNORE_SPACE, arg_) ?
				Option::err_NONE : Option::err_api_reject;
}


Option::Error
InitCommandOption::set(DBDriver* dbd)
{
	return dbd->connected() ? Option::err_connected :
			dbd->set_option(MYSQL_INIT_COMMAND, arg_.c_str()) ?
				Option::err_NONE : Option::err_api_reject;
}


Option::Error
InteractiveOption::set(DBDriver* dbd)
{
	return dbd->connected() ? Option::err_connected :
			dbd->set_option(CLIENT_INTERACTIVE, arg_) ?
				Option::err_NONE : Option::err_api_reject;
}


Option::Error
LocalFilesOption::set(DBDriver* dbd)
{
	return dbd->connected() ? Option::err_connected :
			dbd->set_option(CLIENT_LOCAL_FILES, arg_) ?
				Option::err_NONE : Option::err_api_reject;
}



Option::Error


LocalInfileOption::set(DBDriver* dbd)
{
	return dbd->connected() ? Option::err_connected :
			dbd->set_option(MYSQL_OPT_LOCAL_INFILE, &arg_) ?
				Option::err_NONE : Option::err_api_reject;
}



Option::Error
MultiResultsOption::set(DBDriver* dbd)
{
#if MYSQL_VERSION_ID >= 40101
	if (dbd->connected()) {
		return dbd->set_option(arg_ ? MYSQL_OPTION_MULTI_STATEMENTS_ON :
				MYSQL_OPTION_MULTI_STATEMENTS_OFF) ?
				Option::err_NONE : Option::err_api_reject;
	}
	else {
		return dbd->set_option(CLIENT_MULTI_RESULTS, arg_) ?
				Option::err_NONE : Option::err_api_reject;
	}
#else
	return Option::err_api_limit;
#endif
}




Option::Error
MultiStatementsOption::set(DBDriver* dbd)
{
#if MYSQL_VERSION_ID >= 40101
	if (dbd->connected()) {
		return dbd->set_option(arg_ ? MYSQL_OPTION_MULTI_STATEMENTS_ON :
				MYSQL_OPTION_MULTI_STATEMENTS_OFF) ?
				Option::err_NONE : Option::err_api_reject;
	}
	else {
		return dbd->set_option(CLIENT_MULTI_STATEMENTS, arg_) ?
				Option::err_NONE : Option::err_api_reject;
	}
#else
	return Option::err_api_limit;
#endif
}


Option::Error
NamedPipeOption::set(DBDriver* dbd)
{


	return dbd->connected() ? Option::err_connected :
			dbd->set_option(MYSQL_OPT_NAMED_PIPE) ?
				Option::err_NONE : Option::err_api_reject;
}


Option::Error
NoSchemaOption::set(DBDriver* dbd)
{


	return dbd->connected() ? Option::err_connected :
			dbd->set_option(CLIENT_NO_SCHEMA, arg_) ?
				Option::err_NONE : Option::err_api_reject;
}


Option::Error
ProtocolOption::set(DBDriver* dbd)
{


	return dbd->connected() ? Option::err_connected :
			dbd->set_option(MYSQL_OPT_PROTOCOL, &arg_) ?
				Option::err_NONE : Option::err_api_reject;
}






Option::Error
ReadDefaultFileOption::set(DBDriver* dbd)
{
	return dbd->connected() ? Option::err_connected :
			dbd->set_option(MYSQL_READ_DEFAULT_FILE, arg_.c_str()) ?
				Option::err_NONE : Option::err_api_reject;
}


Option::Error
ReadDefaultGroupOption::set(DBDriver* dbd)
{

	return dbd->connected() ? Option::err_connected :
			dbd->set_option(MYSQL_READ_DEFAULT_GROUP, arg_.c_str()) ?
				Option::err_NONE : Option::err_api_reject;
}




Option::Error
ReadTimeoutOption::set(DBDriver* dbd)
{
#if MYSQL_VERSION_ID >= 40101
	return dbd->connected() ? Option::err_connected :
			dbd->set_option(MYSQL_OPT_READ_TIMEOUT, &arg_) ?
				Option::err_NONE : Option::err_api_reject;
#else
	return Option::err_api_limit;
#endif
}



Option::Error
ReconnectOption::set(DBDriver* dbd)
{
#if MYSQL_VERSION_ID >= 50013
	return dbd->connected() ? Option::err_connected :
			dbd->set_option(MYSQL_OPT_RECONNECT, &arg_) ?
				Option::err_NONE : Option::err_api_reject;
#else
	return Option::err_api_limit;
#endif
}


Option::Error
ReportDataTruncationOption::set(DBDriver* dbd)
{
#if MYSQL_VERSION_ID >= 50003
	return dbd->connected() ? Option::err_connected :
			dbd->set_option(MYSQL_REPORT_DATA_TRUNCATION, &arg_) ?
				Option::err_NONE : Option::err_api_reject;
#else
	return Option::err_api_limit;
#endif
}


Option::Error
SecureAuthOption::set(DBDriver* dbd)
{
#if MYSQL_VERSION_ID >= 40101
	return dbd->connected() ? Option::err_connected :
			dbd->set_option(MYSQL_SECURE_AUTH, &arg_) ?
				Option::err_NONE : Option::err_api_reject;
#else
	return Option::err_api_limit;
#endif
}


Option::Error
SetCharsetDirOption::set(DBDriver* dbd)
{
	return dbd->connected() ? Option::err_connected :
			dbd->set_option(MYSQL_SET_CHARSET_DIR, arg_.c_str()) ?
				Option::err_NONE : Option::err_api_reject;
}


Option::Error
SetCharsetNameOption::set(DBDriver* dbd)
{


	return dbd->connected() ? Option::err_connected :
			dbd->set_option(MYSQL_SET_CHARSET_NAME, arg_.c_str()) ?
				Option::err_NONE : Option::err_api_reject;
}





Option::Error
SetClientIpOption::set(DBDriver* dbd)
{
#if MYSQL_VERSION_ID >= 40101
	return dbd->connected() ? Option::err_connected :
			dbd->set_option(MYSQL_SET_CLIENT_IP, arg_.c_str()) ?
				Option::err_NONE : Option::err_api_reject;
#else

	return Option::err_api_limit;
#endif
}


Option::Error
SharedMemoryBaseNameOption::set(DBDriver* dbd)
{
#if MYSQL_VERSION_ID >= 40100
	return dbd->connected() ? Option::err_connected :
			dbd->set_option(MYSQL_SHARED_MEMORY_BASE_NAME, arg_.c_str()) ?
				Option::err_NONE : Option::err_api_reject;
#else

	return Option::err_api_limit;
#endif
}


Option::Error
SslOption::set(DBDriver* dbd)
{
#if defined(HAVE_MYSQL_SSL_SET)
	return dbd->connected() ? Option::err_connected :
			dbd->enable_ssl(key_.c_str(), cert_.c_str(), ca_.c_str(),
				capath_.c_str(), cipher_.c_str()) ?
				Option::err_NONE : Option::err_api_reject;
#else

	return Option::err_api_limit;
#endif
}






Option::Error
UseEmbeddedConnectionOption::set(DBDriver* dbd)
{
#if MYSQL_VERSION_ID >= 40101
	return dbd->connected() ? Option::err_connected :
			dbd->set_option(MYSQL_OPT_USE_EMBEDDED_CONNECTION) ?
				Option::err_NONE : Option::err_api_reject;
#else

	return Option::err_api_limit;
#endif
}


Option::Error
UseRemoteConnectionOption::set(DBDriver* dbd)
{
#if MYSQL_VERSION_ID >= 40101
	return dbd->connected() ? Option::err_connected :
			dbd->set_option(MYSQL_OPT_USE_REMOTE_CONNECTION) ?
				Option::err_NONE : Option::err_api_reject;
#else

	return Option::err_api_limit;
#endif
}


Option::Error
WriteTimeoutOption::set(DBDriver* dbd)
{
#if MYSQL_VERSION_ID >= 40101
	return dbd->connected() ? Option::err_connected :
			dbd->set_option(MYSQL_OPT_WRITE_TIMEOUT, &arg_) ?
				Option::err_NONE : Option::err_api_reject;
#else

	return Option::err_api_limit;
#endif
}

#endif // !defined(DOXYGEN_IGNORE)






























































} // end namespace mysqlpp



Changes to lib/query.cpp.

1
2



3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
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
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
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
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
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
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
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
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
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
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
/***********************************************************************
 query.cpp - Implements the Query class.




 Copyright (c) 1998 by Kevin Atkinson, (c) 1999-2001 by MySQL AB, and
 (c) 2004-2009 by Educational Technology Resources, Inc.  Others may
 also hold copyrights on code in this file.  See the CREDITS.txt file
 in the top directory of the distribution for details.

 This file is part of MySQL++.

 MySQL++ is free software; you can redistribute it and/or modify it
 under the terms of the GNU Lesser General Public License as published
 by the Free Software Foundation; either version 2.1 of the License, or
 (at your option) any later version.

 MySQL++ is distributed in the hope that it will be useful, but WITHOUT
 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
 License for more details.

 You should have received a copy of the GNU Lesser General Public
 License along with MySQL++; if not, write to the Free Software
 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
 USA
***********************************************************************/

#include "query.h"

#include "autoflag.h"
#include "dbdriver.h"
#include "connection.h"

namespace mysqlpp {

// Force insertfrom() policy template instantiation.  Required to make 
// VC++ happy.
Query::RowCountInsertPolicy<Transaction> RowCountInsertPolicyI(0);
Query::SizeThresholdInsertPolicy<Transaction> SizeThresholdInsertPolicyI(0);
Query::MaxPacketInsertPolicy<Transaction> MaxPacketInsertPolicyI(0);

Query::Query(Connection* c, bool te, const char* qstr) :
#if defined(MYSQLPP_HAVE_STD__NOINIT)
// prevents a double-init memory leak in native VC++ RTL (not STLport!)
std::ostream(std::_Noinit),
#else
std::ostream(0),
#endif
OptionalExceptions(te),
template_defaults(this),
conn_(c),
copacetic_(true)
{
	// Set up our internal IOStreams string buffer
	init(&sbuffer_);

	// Insert passed query string into our string buffer, if given
	if (qstr) {
		sbuffer_.str(qstr);
		seekp(0, std::ios::end);	// allow more insertions at end
	} 

	// Override any global locale setting; we want to use the classic C
	// locale so we don't get weird things like thousands separators in
	// integers inserted into the query stream.
	imbue(std::locale::classic());
}

Query::Query(const Query& q) :
#if defined(MYSQLPP_HAVE_STD__NOINIT)
// ditto above
std::ostream(std::_Noinit),
#else
std::ostream(0),
#endif
OptionalExceptions(q.throw_exceptions())
{
	// Set up our internal IOStreams string buffer
	init(&sbuffer_);

	// See above for reason we override locale for Query streams.
	imbue(std::locale::classic());

	// Copy the other query as best we can
	operator =(q);
}


ulonglong
Query::affected_rows()
{
	return conn_->driver()->affected_rows();
}


int
Query::errnum() const
{
	return conn_->errnum();
}


const char*
Query::error() const
{
	return conn_->error();
}


size_t
Query::escape_string(std::string* ps, const char* original,
		size_t length) const
{
	if (conn_ && *conn_) {
		// Normal case
		return conn_->driver()->escape_string(ps, original, length);
	}
	else {
		// Should only happen in test/test_manip.cpp, since it doesn't
		// want to open a DB connection just to test the manipulators.
		return DBDriver::escape_string_no_conn(ps, original, length);
	}
}


size_t
Query::escape_string(char* escaped, const char* original,
		size_t length) const
{
	if (conn_ && *conn_) {
		// Normal case
		return conn_->driver()->escape_string(escaped, original, length);
	}
	else {
		// Should only happen in test/test_manip.cpp, since it doesn't
		// want to open a DB connection just to test the manipulators.
		return DBDriver::escape_string_no_conn(escaped, original, length);
	}
}


bool
Query::exec(const std::string& str)
{
	if ((copacetic_ = conn_->driver()->execute(str.data(),
			static_cast<unsigned long>(str.length()))) == true) {
		if (parse_elems_.size() == 0) {
			// Not a template query, so auto-reset
			reset();
		}
		return true;
	}
	else if (throw_exceptions()) {
		throw BadQuery(error(), errnum());
	}
	else {
		return false;
	}
}


SimpleResult 
Query::execute() 
{ 
	AutoFlag<> af(template_defaults.processing_);
	return execute(str(template_defaults)); 
}


SimpleResult
Query::execute(SQLQueryParms& p)
{
	AutoFlag<> af(template_defaults.processing_);
	return execute(str(p));
}


SimpleResult
Query::execute(const SQLTypeAdapter& s)
{
	if ((parse_elems_.size() == 2) && !template_defaults.processing_) {
		// We're a template query and this isn't a recursive call, so
		// take s to be a lone parameter for the query.  We will come
		// back in here with a completed query, but the processing_
		// flag will be set, allowing us to avoid an infinite loop.
		AutoFlag<> af(template_defaults.processing_);
		return execute(SQLQueryParms() << s);
	}
	else {
		// Take s to be the entire query string
		return execute(s.data(), s.length());
	}
}


SimpleResult
Query::execute(const char* str, size_t len)
{
	if ((parse_elems_.size() == 2) && !template_defaults.processing_) {
		// We're a template query and this isn't a recursive call, so
		// take s to be a lone parameter for the query.  We will come
		// back in here with a completed query, but the processing_
		// flag will be set, allowing us to avoid an infinite loop.
		AutoFlag<> af(template_defaults.processing_);
		return execute(SQLQueryParms() << str << len );
	}
	if ((copacetic_ = conn_->driver()->execute(str, len)) == true) {
		if (parse_elems_.size() == 0) {
			// Not a template query, so auto-reset
			reset();
		}
		return SimpleResult(conn_, insert_id(), affected_rows(), info());
	}
	else if (throw_exceptions()) {
		throw BadQuery(error(), errnum());
	}
	else {
		return SimpleResult();
	}
}


std::string
Query::info()
{
	return conn_->driver()->query_info();
}


ulonglong
Query::insert_id()
{
	return conn_->driver()->insert_id();
}


bool
Query::more_results()
{
	return conn_->driver()->more_results();
}


Query&
Query::operator=(const Query& rhs)
{
	set_exceptions(rhs.throw_exceptions());
	template_defaults = rhs.template_defaults;
	conn_ = rhs.conn_;
	copacetic_ = rhs.copacetic_;

	*this << rhs.sbuffer_.str();

	parse_elems_  = rhs.parse_elems_;
	parsed_names_ = rhs.parsed_names_;
	parsed_nums_  = rhs.parsed_nums_;

	return *this;
}

Query::operator void*() const
{
	return *conn_ && copacetic_ ? const_cast<Query*>(this) : 0;
}


void
Query::parse()
{
	std::string str = "";
	char num[4];
	std::string name;

	char* s = new char[sbuffer_.str().size() + 1];
	memcpy(s, sbuffer_.str().data(), sbuffer_.str().size());
	s[sbuffer_.str().size()] = '\0';
	const char* s0 = s;

	while (*s) {
		if (*s == '%') {
			// Following might be a template parameter declaration...
			s++;
			if (*s == '%') {
				// Doubled percent sign, so insert literal percent sign.
				str += *s++;
			}
			else if (isdigit(*s)) {
				// Number following percent sign, so it signifies a
				// positional parameter.  First step: find position
				// value, up to 3 digits long.
				num[0] = *s;
				s++;
				if (isdigit(*s)) {
					num[1] = *s;
					num[2] = 0;
					s++;
					if (isdigit(*s)) {
						num[2] = *s;
						num[3] = 0;
						s++;
					}
					else {
						num[2] = 0;
					}
				}
				else {
					num[1] = 0;
				}
				signed char n = atoi(num);

				// Look for option character following position value.
				char option = ' ';
				if (*s == 'q' || *s == 'Q') {
					option = *s++;
				}

				// Is it a named parameter?
				if (*s == ':') {
					// Save all alphanumeric and underscore characters
					// following colon as parameter name.
					s++;
					for (/* */; isalnum(*s) || *s == '_'; ++s) {
						name += *s;
					}

					// Eat trailing colon, if it's present.
					if (*s == ':') {
						s++;
					}

					// Update maps that translate parameter name to
					// number and vice versa.
					if (n >= static_cast<short>(parsed_names_.size())) {
						parsed_names_.insert(parsed_names_.end(),
								static_cast<std::vector<std::string>::size_type>(
										n + 1) - parsed_names_.size(),
								std::string());
					}
					parsed_names_[n] = name;
					parsed_nums_[name] = n;
				}

				// Finished parsing parameter; save it.
				parse_elems_.push_back(SQLParseElement(str, option, n));
				str = "";
				name = "";
			}
			else {
				// Insert literal percent sign, because sign didn't
				// precede a valid parameter string; this allows users
				// to play a little fast and loose with the rules,
				// avoiding a double percent sign here.
				str += '%';
			}
		}
		else {
			// Regular character, so just copy it.
			str += *s++;
		}
	}

	parse_elems_.push_back(SQLParseElement(str, ' ', -1));
	delete[] s0;
}


SQLTypeAdapter*
Query::pprepare(char option, SQLTypeAdapter& S, bool replace)
{
	if (S.is_processed()) {
		return &S;
	}

	if (option == 'q') {
		std::string temp(S.quote_q() ? "'" : "", S.quote_q() ? 1 : 0);

		if (S.escape_q()) {
			char *escaped = new char[S.size() * 2 + 1];
			size_t len = conn_->driver()->escape_string(escaped,
					S.data(), static_cast<unsigned long>(S.size()));
			temp.append(escaped, len);
			delete[] escaped;
		}
		else {
			temp.append(S.data(), S.length());
		}

		if (S.quote_q()) temp.append("'", 1);

		SQLTypeAdapter* ss = new SQLTypeAdapter(temp);

		if (replace) {
			S = *ss;
			S.set_processed();
			delete ss;
			return &S;
		}
		else {
			return ss;
		}
	}
	else if (option == 'Q' && S.quote_q()) {
		std::string temp("'", 1);
		temp.append(S.data(), S.length());
		temp.append("'", 1);
		SQLTypeAdapter *ss = new SQLTypeAdapter(temp);

		if (replace) {
			S = *ss;
			S.set_processed();
			delete ss;
			return &S;
		}
		else {
			return ss;
		}
	}
	else {
		if (replace) {
			S.set_processed();
		}
		return &S;
	}
}


void
Query::proc(SQLQueryParms& p)
{
	sbuffer_.str("");

	for (std::vector<SQLParseElement>::iterator i = parse_elems_.begin();
			i != parse_elems_.end(); ++i) {
		MYSQLPP_QUERY_THISPTR << i->before;
		int num = i->num;
		if (num >= 0) {
			SQLQueryParms* c;
			if (size_t(num) < p.size()) {
				c = &p;
			}
			else if (size_t(num) < template_defaults.size()) {
				c = &template_defaults;
			}
			else {
				*this << " ERROR";
				throw BadParamCount(
						"Not enough parameters to fill the template.");
			}

			SQLTypeAdapter& param = (*c)[num];
			if (param.is_null()) {
				MYSQLPP_QUERY_THISPTR << "NULL";
			}
			else {
				SQLTypeAdapter* ss = pprepare(i->option, param, c->bound());
				MYSQLPP_QUERY_THISPTR << *ss;
				if (ss != &param) {
					// pprepare() returned a new string object instead of
					// updating param in place, so we need to delete it.
					delete ss;
				}
			}
		}
	}
}


void
Query::reset()
{
	seekp(0);
	clear();
	sbuffer_.str("");

	parse_elems_.clear();
	template_defaults.clear();
}


bool
Query::result_empty()
{
	return conn_->driver()->result_empty();
}


StoreQueryResult 
Query::store() 
{ 
	AutoFlag<> af(template_defaults.processing_);
	return store(str(template_defaults)); 
}


StoreQueryResult
Query::store(SQLQueryParms& p)
{
	AutoFlag<> af(template_defaults.processing_);
	return store(str(p));
}


StoreQueryResult
Query::store(const SQLTypeAdapter& s)
{
	if ((parse_elems_.size() == 2) && !template_defaults.processing_) {
		// We're a template query and this isn't a recursive call, so
		// take s to be a lone parameter for the query.  We will come
		// back in here with a completed query, but the processing_
		// flag will be set, allowing us to avoid an infinite loop.
		AutoFlag<> af(template_defaults.processing_);
		return store(SQLQueryParms() << s);
	}
	else {
		// Take s to be the entire query string
		return store(s.data(), s.length());
	}
}


StoreQueryResult
Query::store(const char* str, size_t len)
{
	if ((parse_elems_.size() == 2) && !template_defaults.processing_) {
		// We're a template query and this isn't a recursive call, so
		// take s to be a lone parameter for the query.  We will come
		// back in here with a completed query, but the processing_
		// flag will be set, allowing us to avoid an infinite loop.
		AutoFlag<> af(template_defaults.processing_);
		return store(SQLQueryParms() << str << len );
	}
	MYSQL_RES* res = 0;
	if ((copacetic_ = conn_->driver()->execute(str, len)) == true) {
		res = conn_->driver()->store_result();
	}

	if (res) {
		if (parse_elems_.size() == 0) {
			// Not a template query, so auto-reset
			reset();
		}
		return StoreQueryResult(res, conn_->driver(), throw_exceptions());
	}
	else {
		// Either result set is empty, or there was a problem executing
		// the query or storing its results.  Since it's not an error to
		// use store() with queries that never return results (INSERT,
		// DELETE, CREATE, ALTER...) we need to figure out which case
		// this is.  (You might use store() instead of execute() for
		// such queries when the query strings come from "outside".)
		copacetic_ = (conn_->errnum() == 0);
		if (copacetic_) {
			if (parse_elems_.size() == 0) {
				// Not a template query, so auto-reset
				reset();
			}
			return StoreQueryResult();
		}
		else if (throw_exceptions()) {
			throw BadQuery(error(), errnum());
		}
		else {
			return StoreQueryResult();
		}
	}
}


StoreQueryResult
Query::store_next()
{
#if MYSQL_VERSION_ID > 41000		// only in MySQL v4.1 +
	DBDriver::nr_code rc = conn_->driver()->next_result();
	if (rc == DBDriver::nr_more_results) {
		// There are more results, so return next result set.
		MYSQL_RES* res = conn_->driver()->store_result();
		if (res) {
			return StoreQueryResult(res, conn_->driver(),
					throw_exceptions());
		}
		else {
			// Result set is null, but throw an exception only i it is
			// null because of some error.  If not, it's just an empty
			// result set, which is harmless.  We return an empty result
			// set if exceptions are disabled, as well.
			if (conn_->errnum() && throw_exceptions()) {
				throw BadQuery(error(), errnum());
			}
			else {
				return StoreQueryResult();
			}
		}
	}
	else if (throw_exceptions()) {
		if (rc == DBDriver::nr_error) {
			throw BadQuery(error(), errnum());
		}
		else if (conn_->errnum()) {
			throw BadQuery(error(), errnum());
		}
		else {
			return StoreQueryResult();	// normal end-of-result-sets case
		}
	}
	else {
		return StoreQueryResult();
	}
#else
	return store();
#endif // MySQL v4.1+
}


std::string
Query::str(SQLQueryParms& p)
{
	if (!parse_elems_.empty()) {
		proc(p);
	}

	return sbuffer_.str();
}


UseQueryResult 
Query::use() 
{ 
	AutoFlag<> af(template_defaults.processing_);
	return use(str(template_defaults)); 
}


UseQueryResult
Query::use(SQLQueryParms& p)
{
	AutoFlag<> af(template_defaults.processing_);
	return use(str(p));
}


UseQueryResult
Query::use(const SQLTypeAdapter& s)
{
	if ((parse_elems_.size() == 2) && !template_defaults.processing_) {
		// We're a template query and this isn't a recursive call, so
		// take s to be a lone parameter for the query.  We will come
		// back in here with a completed query, but the processing_
		// flag will be set, allowing us to avoid an infinite loop.
		AutoFlag<> af(template_defaults.processing_);
		return use(SQLQueryParms() << s);
	}
	else {
		// Take s to be the entire query string
		return use(s.data(), s.length());
	}
}


UseQueryResult
Query::use(const char* str, size_t len)
{
	if ((parse_elems_.size() == 2) && !template_defaults.processing_) {
		// We're a template query and this isn't a recursive call, so
		// take s to be a lone parameter for the query.  We will come
		// back in here with a completed query, but the processing_
		// flag will be set, allowing us to avoid an infinite loop.
		AutoFlag<> af(template_defaults.processing_);
		return use(SQLQueryParms() << str << len );
	}
	MYSQL_RES* res = 0;
	if ((copacetic_ = conn_->driver()->execute(str, len)) == true) {
		res = conn_->driver()->use_result();
	}

	if (res) {
		if (parse_elems_.size() == 0) {
			// Not a template query, so auto-reset
			reset();
		}
		return UseQueryResult(res, conn_->driver(), throw_exceptions());
	}
	else {
		// See comments in store() above for why we distinguish between
		// empty result sets and actual error returns here.
		copacetic_ = (conn_->errnum() == 0);
		if (copacetic_) {
			if (parse_elems_.size() == 0) {
				// Not a template query, so auto-reset
				reset();
			}
			return UseQueryResult();
		}
		else if (throw_exceptions()) {
			throw BadQuery(error(), errnum());
		}
		else {
			return UseQueryResult();
		}
	}
}


} // end namespace mysqlpp


|
>
>
>

|
|
|
|



















|
<
|
<
<

<
|
<
<
<
<
<

<
<
<
<
<
|
<
<
<
<
<
|
<
<
|
<
<
<
<
<
|
<
<
<
<
|

<
<
<
<
<
<
<
<
<
<
<
|
<
<
|
<
<
<
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
|
<
<
<
<
<
<
<
<
<
<
|
|
<
<
<

<
<
<
<
|
<
<
<
<
<
|
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
|
|
<
<
<
<
<
<
|
<
<
<
<
<
|
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
|
|
<
<
<
<
<
|
|
<
<
<
<
|
|
|
|
<
<
<
|
|
|
<
<
<
<
<
<
<
|
<
|
<
<
<
|
|

<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
|
<
<
<
<
<
<
<
<
|
<
<
<
<
|
|
<
<
<
<
<
<
<
<
|
<
<
<
<
|
<
<
<
<
<
<
<
<
|
<
<
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
|
<
<
<
|

<
<
<
|
<
<
|
<
<
|
<
<
<
<
<
<
<
|
<
|
|
<
|
<
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
|
<
<
<
<
|

<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
|
<
<
<
<
<
<
<
<
<
<
<
<
|
|
<
<
<
<
<
<
|
<
<
<
|
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
|
|
<
<
<
<
<
<
<
<
<
<
<
<
<
|
<
|
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
|
|
|
|
|
<
<
<
<
|
<
<
<
<
<
<
<
<
<
<
<
<
|
|
<
<
|
|
<
<
<
<
|
|
<
<
<
<
<
<
<
<
<
<
<
<
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
|
<
<
<
<
<
<
<
<
<
|
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
|
<
<
<
<
|
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
|

<
<
|
|
|
|
|
<
<
<
<

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
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













































56
57





58
59




60
61
62
63



64
65
66







67

68



69
70
71


























72














73








74




75
76








77




78








79


80


















81



82
83



84


85


86







87

88
89

90

91















92




93
94







































95












96
97






98



99
100



















101
102













103

104
105

















106
107
108
109
110




111












112
113


114
115




116
117












118



























119









120
121































122




123
124
































125
126


127
128
129
130
131




132
/***********************************************************************
 ssx/main.cpp - Main driver module for ssqlsxlat, which does several
 	data translations related to the SSQLSv2 mechanism of MySQL++.  The
	primary one is SSQLSv2 language files (*.ssqls) to C++ source code,
	but there are others.  Run "ssqlsxlat -?" to get a complete list.

 Copyright (c) 2009 by Warren Young and (c) 2009-2010 by Educational
 Technology Resources, Inc.  Others may also hold copyrights on code
 in this file.  See the CREDITS.txt file in the top directory of the
 distribution for details.

 This file is part of MySQL++.

 MySQL++ is free software; you can redistribute it and/or modify it
 under the terms of the GNU Lesser General Public License as published
 by the Free Software Foundation; either version 2.1 of the License, or
 (at your option) any later version.

 MySQL++ is distributed in the hope that it will be useful, but WITHOUT
 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
 License for more details.

 You should have received a copy of the GNU Lesser General Public
 License along with MySQL++; if not, write to the Free Software
 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
 USA
***********************************************************************/

#include "genv2.h"

#include "parsev2.h"




#include <cmdline.h>











#include <iostream>








using namespace std;





using namespace mysqlpp::ssqlsxlat;

















//// parse_ssqls2 //////////////////////////////////////////////////////


// We were given the name of a putative SSQLS v2 source file; try to



// parse it.




































static ParseV2*
parse_ssqls2(const char* file_name)



{




	try {





		cout << "Parsing SSQLS v2 file " << file_name << "..." << endl;
		ParseV2* pt = new ParseV2(file_name);


















		cout << file_name << " parsed successfully, " <<
				(pt->end() - pt->begin()) << " interesting lines." <<






				endl;





		return pt;
	}













































	catch (const ParseV2::FileException& e) {
		cerr << file_name << ":0" << 





				": file I/O error in SSQLS v2 parse: " <<
				e.what() << endl;




	}
	catch (const ParseV2::ParseException& e) {
		cerr << e.file_name() << ':' << e.line() << ':' <<
				e.what() << endl;



	}
	catch (const std::exception& e) {
		cerr << file_name << ":0" << 







				": critical error in SSQLS v2 parse: " <<

				e.what() << endl;



	}
	return 0;
}


















































//// main //////////////////////////////////////////////////////////////





int








main(int argc, char* argv[])




{








	// Parse the command line


	CommandLine cmdline(argc, argv);


















	if (cmdline) {



		ParseV2* ptree = 0;




		switch (cmdline.input_source()) {


			case CommandLine::ss_ssqls2:


				ptree = parse_ssqls2(cmdline.input());







				break;


			default:

				cerr << "Sorry, I don't yet know what to do with input "

						"source type " << int(cmdline.input_source()) <<















						'!' << endl;




				return 2;
		}




















































		if (cmdline.output_sink() != CommandLine::ss_unknown) {
			if (ptree) {






				switch (cmdline.output_sink()) {



					case CommandLine::ss_ssqls2:
						if (generate_ssqls2(cmdline.output(), ptree)) {



















							return 0;
						}













						else {

							return 2;
						}


















					default:
						cerr << "Sorry, I don't yet know what to do "
								"with sink type " <<
								int(cmdline.output_sink()) << '!' <<




								endl;












						return 2;
				}


			}
			else {




				// Depending on someone farther up the line to write
				// the error message, explaining why we didn't get a












				// parse tree.



























				return 2;









			}	
		}































		else {




			cerr << "Sorry, I don't know how to write C++ output yet." <<
					endl;
































			return 2;
		}


	}
	else {
		return 1;
	}
}





Changes to lib/query.h.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
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
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
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
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
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
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
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
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
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
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
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
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
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
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
/// \file query.h
/// \brief Defines a class for building and executing SQL queries.

/***********************************************************************
 Copyright (c) 1998 by Kevin Atkinson, (c) 1999-2001 by MySQL AB, and
 (c) 2004-2011 by Educational Technology Resources, Inc.  Others may
 also hold copyrights on code in this file.  See the CREDITS.txt file
 in the top directory of the distribution for details.

 This file is part of MySQL++.

 MySQL++ is free software; you can redistribute it and/or modify it
 under the terms of the GNU Lesser General Public License as published
 by the Free Software Foundation; either version 2.1 of the License, or
 (at your option) any later version.

 MySQL++ is distributed in the hope that it will be useful, but WITHOUT
 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
 License for more details.

 You should have received a copy of the GNU Lesser General Public
 License along with MySQL++; if not, write to the Free Software
 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
 USA
***********************************************************************/

#if !defined(MYSQLPP_QUERY_H)
#define MYSQLPP_QUERY_H

#include "common.h"

#include "exceptions.h"
#include "noexceptions.h"
#include "qparms.h"
#include "querydef.h"
#include "result.h"
#include "row.h"
#include "sqlstream.h"
#include "stadapter.h"
#include "transaction.h"

#include <deque>
#include <iomanip>
#include <list>
#include <map>
#include <set>
#include <vector>

#ifdef HAVE_EXT_SLIST
#  include <ext/slist>
#else
#  if defined(HAVE_STD_SLIST) || defined(HAVE_GLOBAL_SLIST)
#      include <slist>
#  endif
#endif

namespace mysqlpp {

#if !defined(DOXYGEN_IGNORE)
// Make Doxygen ignore this
class MYSQLPP_EXPORT Connection;
class MYSQLPP_EXPORT Transaction;
#endif

/// \brief A class for building and executing SQL queries.
///
/// One does not generally create Query objects directly. Instead, call
/// mysqlpp::Connection::query() to get one tied to that connection.
///
/// There are several ways to build and execute SQL queries with this
/// class.
///
/// The way most like other database libraries is to pass a SQL
/// statement in either the form of a C or C++ string to one of the
/// \link mysqlpp::Query::execute() exec*(), \endlink
/// \link mysqlpp::Query::store() store*(), \endlink or use() methods.
/// The query is executed immediately, and any results returned.
///
/// For more complicated queries, it's often more convenient to build up
/// the query string over several C++ statements using Query's stream
/// interface. It works like any other C++ stream (\c std::cout,
/// \c std::ostringstream, etc.) in that you can just insert things
/// into the stream, building the query up piece by piece. When the
/// query string is complete, you  call the overloaded version of
/// \link mysqlpp::Query::execute() exec*(), \endlink
/// \link mysqlpp::Query::store() store*(), \endlink or
/// \link mysqlpp::Query::use() use() \endlink takes no parameters,
/// which executes the built query and returns any results.
///
/// If you are using the library's Specialized SQL Structures feature,
/// Query has several special functions for generating common SQL
/// queries from those structures. For instance, it offers the
/// \link mysqlpp::Query::insert() insert() \endlink method, which
/// builds an INSERT query to add the contents of the SSQLS to the
/// database. As with the stream interface, these methods only build
/// the query string; call one of the parameterless methods mentioned
/// previously to actually execute the query.
///
/// Finally, you can build "template queries". This is something like
/// C's \c printf() function, in that you insert a specially-formatted
/// query string into the object which contains placeholders for data.
/// You call the parse() method to tell the Query object that the query
/// string contains placeholders. Having done that, you call one of the
/// the many
/// \link mysqlpp::Query::execute(const SQLTypeAdapter&) exec*(), \endlink
/// \link mysqlpp::Query::store(const SQLTypeAdapter&) store*(), \endlink
/// or \link mysqlpp::Query::use(const SQLTypeAdapter&) use() \endlink
/// overloads that take SQLTypeAdapter objects.  There are 25 of each by
/// default, differing only in the number of STA objects they take.
/// (See \c lib/querydef.pl if you need to change the limit, or 
/// \c examples/tquery2.cpp for a way around it that doesn't require 
/// changing the library.)  Only the version taking a single STA object
/// is documented below, as to document all of them would just be
/// repetitive.  For each Query method that takes a single STA object,
/// there's a good chance there's a set of undocumented overloads that
/// take more of them for the purpose of filling out a template query.
///
/// See the user manual for more details about these options.

class MYSQLPP_EXPORT Query :
		public std::ostream,
		public OptionalExceptions
{
public:
	// Bring in InsertPolicy template as part of this class's interface,
	// separate only in the sense that it's a self-contained concept.
	#define MYSQLPP_DEFINE_INSERT_POLICY_TEMPLATES
	#include "insertpolicy.h"
	#undef MYSQLPP_DEFINE_INSERT_POLICY_TEMPLATES

	/// \brief Create a new query object attached to a connection.
	///
	/// This is the constructor used by mysqlpp::Connection::query().
	///
	/// \param c connection the finished query should be sent out on
	/// \param te if true, throw exceptions on errors
	/// \param qstr an optional initial query string
	Query(Connection* c, bool te = true, const char* qstr = 0);

	/// \brief Create a new query object as a copy of another.
	///
	/// This is \b not a traditional copy ctor!  Its only purpose is to
	/// make it possible to assign the return of Connection::query()
	/// to an empty Query object.  In particular, the stream buffer and
	/// template query stuff will be empty in the copy, regardless of
	/// what values they have in the original.
	Query(const Query& q);

	/// \brief Return the number of rows affected by the last query
	ulonglong affected_rows();

	/// \brief Return a SQL-escaped version of a character buffer
	///
	/// \param ps pointer to C++ string to hold escaped version; if
	/// original is 0, also holds the original data to be escaped
	/// \param original if given, pointer to the character buffer to
	/// escape instead of contents of *ps
	/// \param length if both this and original are given, number of
	/// characters to escape instead of ps->length()
	///
	/// \retval number of characters placed in *ps
	///
	/// \see comments for escape_string(char*, const char*, size_t)
	/// and DBDriver::escape_string(std::string*, const char *, size_t)
	/// for further details.
	size_t escape_string(std::string* ps, const char* original = 0,
			size_t length = 0) const;

	/// \brief Return a SQL-escaped version of the given character
	/// buffer
	///
	/// \param escaped character buffer to hold escaped version; must
	/// point to at least (length * 2 + 1) bytes
	/// \param original pointer to the character buffer to escape
	/// \param length number of characters to escape
	///
	/// \retval number of characters placed in escaped
	///
	/// DBDriver provides two versions of this method and 
	/// Query::escape_string() calls the appropriate one based on whether
	/// or not a database connection is available.  If the connection
	/// is available, it can call the DBDriver::escape_string() method.
	/// If there is no database connection available (normally only in
	/// testing), then DBDriver provides a static version of the function 
	/// that doesn't use a database connection.
	///
	/// \see comments for DBDriver::escape_string(char*, const char*, size_t),
	/// DBDriver::escape_string_no_conn(char*, const char*, size_t)
	/// for further details.
	size_t escape_string(char* escaped, const char* original,
			size_t length) const;

	/// \brief Get the last error number that was set.
	///
	/// This just delegates to Connection::errnum().  Query has nothing
	/// extra to say, so use either, as makes sense in your program.
	int errnum() const;

	/// \brief Get the last error message that was set.
	///
	/// This just delegates to Connection::error().  Query has nothing
	/// extra to say, so use either, as makes sense in your program.
	const char* error() const;

	/// \brief Returns information about the most recently executed
	/// query.
	std::string info();

	/// \brief Get ID generated for an AUTO_INCREMENT column in the
	/// previous INSERT query.
	///
	/// \retval 0 if the previous query did not generate an ID.  Use
	/// the SQL function LAST_INSERT_ID() if you need the last ID
	/// generated by any query, not just the previous one.  This
	/// applies to stored procedure calls because this function returns
	/// the ID generated by the last query, which was a CALL statement,
	/// and CALL doesn't generate IDs.  You need to use LAST_INSERT_ID()
	/// to get the ID in this case.
	ulonglong insert_id();

	/// \brief Assign another query's state to this object
	///
	/// The same caveats apply to this operator as apply to the copy
	/// ctor.
	Query& operator=(const Query& rhs);

	/// \brief Test whether the object has experienced an error condition
	///
	/// Allows for code constructs like this:
	///
	/// \code
	///	Query q = conn.query();
	///	.... use query object
	///	if (q) {
	///	    ... no problems in using query object
	///	}
	///	else {
	///	    ... an error has occurred
	///	}
	/// \endcode
	///
	/// This method returns false if either the Query object or its
	/// associated Connection object has seen an error condition since
	/// the last operation.
	operator void*() const;

	/// \brief Returns true if the query object is not in a bad state
	///
	/// This just returns the opposite of operator void*(), and is
	/// required only because basic_ios defines it, so we have to
	/// override it to get Query-specific behavior in code like this:
	///
	/// \code if (!query) ... \endcode
	bool operator !() const { return !operator void*(); }

	/// \brief Treat the contents of the query string as a template
	/// query.
	///
	/// This method sets up the internal structures used by all of the
	/// other members that accept template query parameters.  See the
	/// "Template Queries" chapter in the user manual for more
	/// information.
	void parse();

	/// \brief Reset the query object so that it can be reused.
	///
	/// As of v3.0, Query objects auto-reset upon query execution unless
	/// you've set it up for making template queries.  (It can't auto-reset
	/// in that situation, because it would forget the template info.)
	/// Therefore, the only time you must call this is if you have a Query
	/// object set up for making template queries, then want to build
	/// queries using one of the other methods.  (Static strings, SSQLS,
	/// or the stream interface.)
	void reset();

	/// \brief Returns true if the most recent result set was empty
	///
	/// Wraps DBDriver::result_empty()
	bool result_empty();

	/// \brief Get built query as a C++ string
	std::string str() { return str(template_defaults); }

	/// \brief Get built query as a C++ string with template query
	/// parameter substitution.
	///
	/// \param arg0 the value to substitute for the first template query
	/// parameter; because SQLTypeAdapter implicitly converts from many
	/// different data types, this method is very flexible in what it
	/// accepts as a parameter.  You shouldn't have to use the
	/// SQLTypeAdapter data type directly in your code.
	///
	/// There many more overloads of this type (25 total, by default;
	/// see \c lib/querydef.pl), each taking one more SQLTypeAdapter object
	/// than the previous one.  See the template query overview above
	/// for more about this topic.
	std::string str(const SQLTypeAdapter& arg0)
			{ return str(SQLQueryParms() << arg0); }

	/// \brief Get built query as a null-terminated C++ string
	///
	/// \param p template query parameters to use, overriding the ones
	/// this object holds, if any
	std::string str(SQLQueryParms& p);

	/// \brief Execute a built-up query
	///
	/// Same as exec(), except that it uses the query string built up
	/// within the query object already instead of accepting a query
	/// string from the caller.
	///
	/// \return true if query was executed successfully
	///
	/// \sa exec(const std::string& str), execute(), store(),
	/// storein(), and use()
	bool exec() { return exec(str(template_defaults)); }

	/// \brief Execute a query
	///
	/// Same as execute(), except that it only returns a flag indicating
	/// whether the query succeeded or not.  It is basically a thin
	/// wrapper around the C API function \c mysql_real_query().
	///
	/// \param str the query to execute
	///
	/// \return true if query was executed successfully
	///
	/// \sa execute(), store(), storein(), and use()
	bool exec(const std::string& str);

	/// \brief Execute built-up query
	///
	/// Use one of the execute() overloads if you don't expect the
	/// server to return a result set. For instance, a DELETE query.
	/// The returned SimpleResult object contains status information from
	/// the server, such as whether the query succeeded, and if so how
	/// many rows were affected.
	///
	/// This overloaded version of execute() simply executes the query
	/// that you have built up in the object in some way. (For instance,
	/// via the insert() method, or by using the object's stream
	/// interface.)
	///
	/// \return SimpleResult status information about the query
	///
	/// \sa exec(), store(), storein(), and use()
	SimpleResult execute(); 

	/// \brief Execute template query using given parameters.
	///
	/// This method should only be used by code that doesn't know,
	/// at compile time, how many parameters it will have.  This is
	/// useful within the library, and also for code that builds
	/// template queries dynamically, at run time.
	///
	/// \param p parameters to use in the template query.
	SimpleResult execute(SQLQueryParms& p);

	/// \brief Execute a query that returns no rows
	///
	/// \param str if this object is set up as a template query, this is
	/// the value to substitute for the first template query parameter;
	/// else, it is the SQL query string to execute
	///
	/// Because SQLTypeAdapter can be initialized from either a C string
	/// or a C++ string, this overload accepts query strings in either
	/// form.  Beware, SQLTypeAdapter also accepts many other data types
	/// (this is its \e raison \e d'etre), so it will let you write code
	/// that compiles but results in bogus SQL queries.
	///
	/// To support template queries, there many more overloads of this
	/// type (25 total, by default; see \c lib/querydef.pl), each taking
	/// one more SQLTypeAdapter object than the previous one.  See the
	/// template query overview above for more about this topic.
	SimpleResult execute(const SQLTypeAdapter& str);

	/// \brief Execute query in a known-length string of characters.
	/// This can include null characters.
	///
	/// Executes the query immediately, and returns the results.
	SimpleResult execute(const char* str, size_t len);

	/// \brief Execute a query that can return rows, with access to
	/// the rows in sequence
	/// 
	/// Use one of the use() overloads if memory efficiency is
	/// important.  They return an object that can walk through
	/// the result records one by one, without fetching the entire
	/// result set from the server.  This is superior to store()
	/// when there are a large number of results; store() would have to
	/// allocate a large block of memory to hold all those records,
	/// which could cause problems.
	///
	/// A potential downside of this method is that MySQL database
	/// resources are tied up until the result set is completely
	/// consumed.  Do your best to walk through the result set as
	/// expeditiously as possible.
	///
	/// The name of this method comes from the MySQL C API function
	/// that initiates the retrieval process, \c mysql_use_result().
	/// This method is implemented in terms of that function.
	///
	/// This function has the same set of overloads as execute().
	///
	/// \return UseQueryResult object that can walk through result set serially
	///
	/// \sa exec(), execute(), store() and storein()
	UseQueryResult use();

	/// \brief Execute a template query that can return rows, with
	/// access to the rows in sequence
	///
	/// This method should only be used by code that doesn't know,
	/// at compile time, how many parameters it will have.  This is
	/// useful within the library, and also for code that builds
	/// template queries dynamically, at run time.
	///
	/// \param p parameters to use in the template query.
	UseQueryResult use(SQLQueryParms& p);

	/// \brief Execute a query that can return rows, with access to
	/// the rows in sequence
	///
	/// \param str if this object is set up as a template query, this is
	/// the value to substitute for the first template query parameter;
	/// else, it is the SQL query string to execute
	///
	/// Because SQLTypeAdapter can be initialized from either a C string
	/// or a C++ string, this overload accepts query strings in either
	/// form.  Beware, SQLTypeAdapter also accepts many other data types
	/// (this is its \e raison \e d'etre), so it will let you write code
	/// that compiles but results in bogus SQL queries.
	///
	/// To support template queries, there many more overloads of this
	/// type (25 total, by default; see \c lib/querydef.pl), each taking
	/// one more SQLTypeAdapter object than the previous one.  See the
	/// template query overview above for more about this topic.
	UseQueryResult use(const SQLTypeAdapter& str);

	/// \brief Execute a query that can return rows, with access to
	/// the rows in sequence
	///
	/// This overload is for situations where you have the query in a
	/// C string and have its length already.  If you want to execute
	/// a query in a null-terminated C string or have the query string
	/// in some other form, you probably want to call
	/// use(const SQLTypeAdapter&) instead.  SQLTypeAdapter converts
	/// from plain C strings and other useful data types implicitly.
	UseQueryResult use(const char* str, size_t len);

	/// \brief Execute a query that can return a result set
	///
	/// Use one of the store() overloads to execute a query and retrieve
	/// the entire result set into memory.  This is useful if you
	/// actually need all of the records at once, but if not, consider
	/// using one of the use() methods instead, which returns the results
	/// one at a time, so they don't allocate as much memory as store().
	///
	/// You must use store(), storein() or use() for \c SELECT, \c SHOW,
	/// \c DESCRIBE and \c EXPLAIN queries.  You can use these functions
	/// with other query types, but since they don't return a result
	/// set, exec() and execute() are more efficient.
	///
	/// The name of this method comes from the MySQL C API function it
	/// is implemented in terms of, \c mysql_store_result().
	///
	/// This function has the same set of overloads as execute().
	///
	/// \return StoreQueryResult object containing entire result set
	///
	/// \sa exec(), execute(), storein(), and use()
	StoreQueryResult store();

	/// \brief Store results from a template query using given parameters.
	///
	/// This method should only be used by code that doesn't know,
	/// at compile time, how many parameters it will have.  This is
	/// useful within the library, and also for code that builds
	/// template queries dynamically, at run time.
	///
	/// \param p parameters to use in the template query.
	StoreQueryResult store(SQLQueryParms& p);

	/// \brief Execute a query that can return rows, returning all
	/// of the rows in a random-access container
	///
	/// \param str if this object is set up as a template query, this is
	/// the value to substitute for the first template query parameter;
	/// else, it is the SQL query string to execute
	///
	/// Because SQLTypeAdapter can be initialized from either a C string
	/// or a C++ string, this overload accepts query strings in either
	/// form.  Beware, SQLTypeAdapter also accepts many other data types
	/// (this is its \e raison \e d'etre), so it will let you write code
	/// that compiles but results in bogus SQL queries.
	///
	/// To support template queries, there many more overloads of this
	/// type (25 total, by default; see \c lib/querydef.pl), each taking
	/// one more SQLTypeAdapter object than the previous one.  See the
	/// template query overview above for more about this topic.
	StoreQueryResult store(const SQLTypeAdapter& str);

	/// \brief Execute a query that can return rows, returning all
	/// of the rows in a random-access container
	///
	/// This overload is for situations where you have the query in a
	/// C string and have its length already.  If you want to execute
	/// a query in a null-terminated C string or have the query string
	/// in some other form, you probably want to call
	/// store(const SQLTypeAdapter&) instead.  SQLTypeAdapter converts
	/// from plain C strings and other useful data types implicitly.
	StoreQueryResult store(const char* str, size_t len);

	/// \brief Execute a query, and call a functor for each returned row
	///
	/// This method wraps a use() query, calling the given functor for
	/// every returned row.  It is analogous to STL's for_each()
	/// algorithm, but instead of iterating over some range within a
	/// container, it iterates over a result set produced by a query.
	///
	/// \param query the query string
	/// \param fn the functor called for each row
	/// \return a copy of the passed functor
	template <typename Function>
	Function for_each(const SQLTypeAdapter& query, Function fn)
	{	
		mysqlpp::UseQueryResult res = use(query);
		if (res) {
			mysqlpp::NoExceptions ne(res);
			while (mysqlpp::Row row = res.fetch_row()) {
				fn(row);
			}
		}

		return fn;
	}

	/// \brief Execute the query, and call a functor for each returned row
	///
	/// Just like for_each(const SQLTypeAdapter&, Function), but it uses
	/// the query string held by the Query object already
	///
	/// \param fn the functor called for each row
	/// \return a copy of the passed functor
	template <typename Function>
	Function for_each(Function fn)
	{	
		mysqlpp::UseQueryResult res = use();
		if (res) {
			mysqlpp::NoExceptions ne(res);
			while (mysqlpp::Row row = res.fetch_row()) {
				fn(row);
			}
		}

		return fn;
	}

	/// \brief Run a functor for every row in a table
	///
	/// Just like for_each(Function), except that it builds a
	/// "select * from TABLE" query using the SQL table name from
	/// the SSQLS instance you pass.
	///
	/// \param ssqls the SSQLS instance to get a table name from
	/// \param fn the functor called for each row
	///
	/// \return a copy of the passed functor
	template <class SSQLS, typename Function>
	Function for_each(const SSQLS& ssqls, Function fn)
	{	
		std::string query("select * from `");
		query += ssqls.table();
      query += '`';
		mysqlpp::UseQueryResult res = use(query);
		if (res) {
			mysqlpp::NoExceptions ne(res);
			while (mysqlpp::Row row = res.fetch_row()) {
				fn(row);
			}
		}

		return fn;
	}

	/// \brief Execute a query, conditionally storing each row in a
	/// container
	///
	/// This method wraps a use() query, calling the given functor for
	/// every returned row, and storing the results in the given
	/// sequence container if the functor returns true.
	///
	/// This is analogous to the STL copy_if() algorithm, except that
	/// the source rows come from a database query instead of another
	/// container.  (copy_if() isn't a standard STL algorithm, but only
	/// due to an oversight by the standardization committee.)  This
	/// fact may help you to remember the order of the parameters: the
	/// container is the destination, the query is the source, and the
	/// functor is the predicate; it's just like an STL algorithm.
	///
	/// \param con the destination container; needs a push_back() method
	/// \param query the query string
	/// \param fn the functor called for each row
	/// \return a copy of the passed functor
	template <class Sequence, typename Function>
	Function store_if(Sequence& con, const SQLTypeAdapter& query, Function fn)
	{	
		mysqlpp::UseQueryResult res = use(query);
		if (res) {
			mysqlpp::NoExceptions ne(res);
			while (mysqlpp::Row row = res.fetch_row()) {
				if (fn(row)) {
					con.push_back(row);
				}
			}
		}

		return fn;
	}

	/// \brief Pulls every row in a table, conditionally storing each
	/// one in a container
	///
	/// Just like store_if(Sequence&, const SQLTypeAdapter&, Function), but
	/// it uses the SSQLS instance to construct a "select * from TABLE"
	/// query, using the table name field in the SSQLS.
	///
	/// \param con the destination container; needs a push_back() method
	/// \param ssqls the SSQLS instance to get a table name from
	/// \param fn the functor called for each row
	/// \return a copy of the passed functor
	template <class Sequence, class SSQLS, typename Function>
	Function store_if(Sequence& con, const SSQLS& ssqls, Function fn)
	{	
		std::string query("select * from `");
		query += ssqls.table();
      query += '`';
		mysqlpp::UseQueryResult res = use(query);
		if (res) {
			mysqlpp::NoExceptions ne(res);
			while (mysqlpp::Row row = res.fetch_row()) {
				if (fn(row)) {
					con.push_back(row);
				}
			}
		}

		return fn;
	}

	/// \brief Execute the query, conditionally storing each row in a
	/// container
	///
	/// Just like store_if(Sequence&, const SQLTypeAdapter&, Function), but
	/// it uses the query string held by the Query object already
	///
	/// \param con the destination container; needs a push_back() method
	/// \param fn the functor called for each row
	/// \return a copy of the passed functor
	template <class Sequence, typename Function>
	Function store_if(Sequence& con, Function fn)
	{	
		mysqlpp::UseQueryResult res = use();
		if (res) {
			mysqlpp::NoExceptions ne(res);
			while (mysqlpp::Row row = res.fetch_row()) {
				if (fn(row)) {
					con.push_back(row);
				}
			}
		}

		return fn;
	}

	/// \brief Return next result set, when processing a multi-query
	///
	/// There are two cases where you'd use this function instead of
	/// the regular store() functions.
	/// 
	/// First, when handling the result of executing multiple queries
	/// at once.  (See <a
	/// href="http://dev.mysql.com/doc/mysql/en/c-api-multiple-queries.html">this
	/// page</a> in the MySQL documentation for details.) 
	///
	/// Second, when calling a stored procedure, MySQL can return the
	/// result as a set of results.
	///
	/// In either case, you must consume all results before making
	/// another MySQL query, even if you don't care about the remaining
	/// results or result sets.
	///
	/// As the MySQL documentation points out, you must set the
	/// MYSQL_OPTION_MULTI_STATEMENTS_ON flag on the connection in order
	/// to use this feature.  See Connection::set_option().
	///
	/// Multi-queries only exist in MySQL v4.1 and higher.  Therefore,
	/// this function just wraps store() when built against older API
	/// libraries.
	///
	/// \return StoreQueryResult object containing the next result set.
	StoreQueryResult store_next();

	/// \brief Return whether more results are waiting for a multi-query
	/// or stored procedure response.
	///
	/// If this function returns true, you must call store_next() to
	/// fetch the next result set before you can execute more queries.
	///
	/// Wraps mysql_more_results() in the MySQL C API.  That function
	/// only exists in MySQL v4.1 and higher.  Therefore, this function
	/// always returns false when built against older API libraries.
	///
	/// \return true if another result set exists
	bool more_results();

	/// \brief Execute a query, storing the result set in an STL
	/// sequence container.
	///
	/// This function works much like store() from the caller's
	/// perspective, because it returns the entire result set at once.
	/// It's actually implemented in terms of use(), however, so that
	/// memory for the result set doesn't need to be allocated twice.
	///
	/// There are many overloads for this function, pretty much the same
	/// as for execute(), except that there is a Container parameter at
	/// the front of the list.  So, you can pass a container and a query
	/// string, or a container and template query parameters.
	///
	/// \param con any STL sequence container, such as \c std::vector
	///
	/// \sa exec(), execute(), store(), and use()
	template <class Sequence>
	void storein_sequence(Sequence& con)
	{
		storein_sequence(con, str(template_defaults));
	}

	/// \brief Executes a query, storing the result rows in an STL
	/// sequence container.
	///
	/// \param con the container to store the results in
	///
	/// \param s if Query is set up as a template query, this is the value
	/// to substitute for the first template query parameter; else, the
	/// SQL query string
	///
	/// There many more overloads of this type (25 total, by default;
	/// see \c lib/querydef.pl), each taking one more SQLTypeAdapter object
	/// than the previous one.  See the template query overview above
	/// for more about this topic.
	template <class Sequence>
	void storein_sequence(Sequence& con, const SQLTypeAdapter& s)
	{
		if (UseQueryResult result = use(s)) {
			while (1) {
				MYSQL_ROW d = result.fetch_raw_row();
				if (!d) break;
				Row row(d, &result, result.fetch_lengths(),
						throw_exceptions());
				if (!row) break;
				con.push_back(typename Sequence::value_type(row));
			}
		}
		else if (!result_empty()) {
			// Underlying MySQL C API returned an empty result for this
			// query, but it also says it should have returned
			// something.  Reasons it can do that are given here:
			// http://dev.mysql.com/doc/refman/5.5/en/null-mysql-store-result.html
			// Regardless, it means the C library barfed, so we can't
			// just return an empty result set.
			copacetic_ = false;
			if (throw_exceptions()) {
				throw UseQueryError("Bogus empty result");
			}
		}
		// else, it was *supposed* to return nothing, because query was
		// an INSERT, CREATE, etc. sort.  So, leave con untouched.
	}

	/// \brief Execute template query using given parameters, storing
	/// the results in a sequence type container.
	///
	/// This method should only be used by code that doesn't know,
	/// at compile time, how many parameters it will have.  This is
	/// useful within the library, and also for code that builds
	/// template queries dynamically, at run time.
	///
	/// \param con container that will receive the results
	/// \param p parameters to use in the template query.
	template <class Seq>
	void storein_sequence(Seq& con, SQLQueryParms& p)
	{
		storein_sequence(con, str(p));
	}

	/// \brief Execute a query, storing the result set in an STL
	/// associative container.
	///
	/// The same thing as storein_sequence(), except that it's used with
	/// associative STL containers, such as \c std::set.  Other than
	/// that detail, that method's comments apply equally well to this
	/// one.
	template <class Set>
	void storein_set(Set& con)
	{
		storein_set(con, str(template_defaults));
	}

	/// \brief Executes a query, storing the result rows in an STL
	/// set-associative container.
	///
	/// \param con the container to store the results in
	///
	/// \param s if Query is set up as a template query, this is the value
	/// to substitute for the first template query parameter; else, the
	/// SQL query string
	///
	/// There many more overloads of this type (25 total, by default;
	/// see \c lib/querydef.pl), each taking one more SQLTypeAdapter object
	/// than the previous one.  See the template query overview above
	/// for more about this topic.
	template <class Set>
	void storein_set(Set& con, const SQLTypeAdapter& s)
	{
		if (UseQueryResult result = use(s)) {
			while (1) {
				MYSQL_ROW d = result.fetch_raw_row();
				if (!d) break;
				Row row(d, &result, result.fetch_lengths(),
						throw_exceptions());
				if (!row) break;
				con.insert(typename Set::value_type(row));
			}
		}
		else if (!result_empty()) {
			// Underlying MySQL C API returned an empty result for this
			// query, but it also says it should have returned
			// something.  Reasons it can do that are given here:
			// http://dev.mysql.com/doc/refman/5.5/en/null-mysql-store-result.html
			// Regardless, it means the C library barfed, so we can't
			// just return an empty result set.
			copacetic_ = false;
			if (throw_exceptions()) {
				throw UseQueryError("Bogus empty result");
			}
		}
		// else, it was *supposed* to return nothing, because query was
		// an INSERT, CREATE, etc. sort.  So, leave con untouched.
	}

	/// \brief Execute template query using given parameters, storing
	/// the results in a set type container.
	///
	/// This method should only be used by code that doesn't know,
	/// at compile time, how many parameters it will have.  This is
	/// useful within the library, and also for code that builds
	/// template queries dynamically, at run time.
	///
	/// \param con container that will receive the results
	/// \param p parameters to use in the template query.
	template <class Set>
	void storein_set(Set& con, SQLQueryParms& p)
	{
		storein_set(con, str(p));
	}

	/// \brief Execute a query, and store the entire result set
	/// in an STL container.
	///
	/// This is a set of specialized template functions that call either
	/// storein_sequence() or storein_set(), depending on the type of
	/// container you pass it. It understands \c std::vector, \c deque,
	/// \c list, \c slist (a common C++ library extension), \c set,
	/// and \c multiset.
	///
	/// Like the functions it wraps, this is actually an overloaded set
	/// of functions. See the other functions' documentation for details.
	///
	/// Use this function if you think you might someday switch your
	/// program from using a set-associative container to a sequence
	/// container for storing result sets, or vice versa.
	///
	/// See exec(), execute(), store(), and use() for alternative
	/// query execution mechanisms.
	template <class Container>
	void storein(Container& con)
	{
		storein(con, str(template_defaults));
	}

	/// \brief Store template query results into a container
	///
	/// This method is not intended to be used directly.  It is part
	/// of the call chain in processing calls to one of the many
	/// storein() overloads that take a container and one or more
	/// SQLTypeAdapter parameters.
	template <class T>
	void storein(T& con, SQLQueryParms& p)
	{
		storein(con, str(p));
	}

	/// \brief Specialization of storein_sequence() for \c std::vector
	template <class T>
	void storein(std::vector<T>& con, const SQLTypeAdapter& s)
	{
		storein_sequence(con, s);
	}

	/// \brief Specialization of storein_sequence() for \c std::deque
	template <class T>
	void storein(std::deque<T>& con, const SQLTypeAdapter& s)
	{
		storein_sequence(con, s);
	}

	/// \brief Specialization of storein_sequence() for \c std::list
	template <class T>
	void storein(std::list<T>& con, const SQLTypeAdapter& s)
	{
		storein_sequence(con, s);
	}

#if defined(HAVE_EXT_SLIST)
	/// \brief Specialization of storein_sequence() for g++ STL
	/// extension \c slist
	template <class T>
	void storein(__gnu_cxx::slist<T>& con, const SQLTypeAdapter& s)
	{
		storein_sequence(con, s);
	}
#elif defined(HAVE_GLOBAL_SLIST)
	/// \brief Specialization of storein_sequence() for STL
	/// extension \c slist
	///
	/// This is primarily for older versions of g++, which put \c slist
	/// in the global namespace.  This is a common language extension,
	/// so this may also work for other compilers.
	template <class T>
	void storein(slist<T>& con, const SQLTypeAdapter& s)
	{
		storein_sequence(con, s);
	}
#elif defined(HAVE_STD_SLIST)
	/// \brief Specialization of storein_sequence() for STL
	/// extension \c slist
	///
	/// This is for those benighted compilers that include an \c slist
	/// implementation, but erroneously put it in the \c std namespace!
	template <class T>
	void storein(std::slist<T>& con, const SQLTypeAdapter& s)
	{
		storein_sequence(con, s);
	}
#endif

	/// \brief Specialization of storein_set() for \c std::set
	template <class T>
	void storein(std::set<T>& con, const SQLTypeAdapter& s)
	{
		storein_set(con, s);
	}

	/// \brief Specialization of storein_set() for \c std::multiset
	template <class T>
	void storein(std::multiset<T>& con, const SQLTypeAdapter& s)
	{
		storein_set(con, s);
	}

	/// \brief Replace an existing row's data with new data.
	///
	/// This function builds an UPDATE SQL query using the new row data
	/// for the SET clause, and the old row data for the WHERE clause.
	/// One uses it with MySQL++'s Specialized SQL Structures mechanism.
	///
	/// \param o old row
	/// \param n new row
	///
	/// \sa insert(), replace()
	template <class T>
	Query& update(const T& o, const T& n)
	{
		reset();

		// Cast required for VC++ 2003 due to error in overloaded operator
		// lookup logic.  For an explanation of the problem, see:
		// http://groups-beta.google.com/group/microsoft.public.vc.stl/browse_thread/thread/9a68d84644e64f15
		MYSQLPP_QUERY_THISPTR << std::setprecision(16) <<
				"UPDATE `" << o.table() << "` SET " << n.equal_list() <<
				" WHERE " << o.equal_list(" AND ", sql_use_compare);
		return *this;
	}

	/// \brief Insert a new row.
	///
	/// This function builds an INSERT SQL query.  One uses it with
	/// MySQL++'s Specialized SQL Structures mechanism.
	///
	/// \param v new row
	///
	/// \sa replace(), update()
	template <class T>
	Query& insert(const T& v)
	{
		reset();

		MYSQLPP_QUERY_THISPTR << std::setprecision(16) <<
				"INSERT INTO `" << v.table() << "` (" <<
				v.field_list() << ") VALUES (" <<
				v.value_list() << ')';
		return *this;
	}

	/// \brief Insert multiple new rows.
	///
	/// Builds an INSERT SQL query using items from a range within an
	/// STL container.  Insert the entire contents of the container by
	/// using the begin() and end() iterators of the container as
	/// parameters to this function.
	///
	/// \param first iterator pointing to first element in range to
	///    insert
	/// \param last iterator pointing to one past the last element to
	///    insert
	///
	/// \sa insertfrom(), replace(), update()
	template <class Iter>
	Query& insert(Iter first, Iter last)
	{
		reset();

		if (first != last) {
			// Build SQL for first item in the container.  It's special
			// because we need the table name and field list.
			MYSQLPP_QUERY_THISPTR << std::setprecision(16) <<
					"INSERT INTO `" << first->table() << "` (" <<
					first->field_list() << ") VALUES (" <<
					first->value_list() << ')';

			// Now insert any remaining container elements.  Be careful
			// hacking on the iterator use here: we want it to work
			// with containers providing only a forward iterator.
			Iter it = first;
			while (++it != last) {
				MYSQLPP_QUERY_THISPTR << ",(" << it->value_list() << ')';
			}
		}

		return *this;
	}

	/// \brief Insert multiple new rows using an insert policy to
	/// control how the INSERT statements are created using
	/// items from an STL container.
	///
	/// \param first iterator pointing to first element in range to
	///    insert
	/// \param last iterator pointing to one past the last element to
	///    insert
	/// \param policy insert policy object, see insertpolicy.h for
	/// details
	///
	/// \sa insert()
	template <class Iter, class InsertPolicy>
	Query& insertfrom(Iter first, Iter last, InsertPolicy& policy)
	{
		bool success = true;
		bool empty = true;

		reset();

		if (first == last) {
			return *this;   // empty set!
		}

		typename InsertPolicy::access_controller ac(*conn_);
		
		for (Iter it = first; it != last; ++it) {
			if (policy.can_add(int(tellp()), *it)) {
				if (empty) {
					MYSQLPP_QUERY_THISPTR << std::setprecision(16) <<
						"INSERT INTO `" << it->table() << "` (" <<
						it->field_list() << ") VALUES (";
				} 
				else {
					MYSQLPP_QUERY_THISPTR << ",(";
				}

				MYSQLPP_QUERY_THISPTR << it->value_list() << ')';

				empty = false;
			} 
			else {
				// Execute what we've built up already, if there is anything
				if (!empty) {
					if (!exec()) {
						success = false;
						break;
					}

					empty = true;
				}

				// If we _still_ can't add, the policy is too strict
				if (policy.can_add(int(tellp()), *it)) {
					MYSQLPP_QUERY_THISPTR << std::setprecision(16) <<
						"INSERT INTO `" << it->table() << "` (" <<
						it->field_list() << ") VALUES (" <<
						it->value_list() << ')';

					empty = false;
				} 
				else {
					// At this point all we can do is give up
					if (throw_exceptions()) {
						throw BadInsertPolicy("Insert policy is too strict");
					}

					success = false;
					break;
				}
			}
		}

		// We might need to execute the last query here.
		if (success && !empty && !exec()) {
			success = false;
		}

		if (success) {
			ac.commit();
		} 
		else {
			ac.rollback();
		}

		return *this;
	}

	/// \brief Replace multiple new rows using an insert policy to
	/// control how the REPLACE statements are created using
	/// items from an STL container.
	///
	/// \param first iterator pointing to first element in range to
	///    replace
	/// \param last iterator pointing to one past the last element to
	///    replace
	/// \param policy insert policy object, see insertpolicy.h for
	/// details
	///
	/// \sa insert()
	template <class Iter, class InsertPolicy>
	Query& replacefrom(Iter first, Iter last, InsertPolicy& policy)
	{
		bool success = true;
		bool empty = true;

		reset();

		if (first == last) {
			return *this;   // empty set!
		}

		typename InsertPolicy::access_controller ac(*conn_);

		for (Iter it = first; it != last; ++it) {
			if (policy.can_add(int(tellp()), *it)) {
				if (empty) {
					MYSQLPP_QUERY_THISPTR << std::setprecision(16) <<
						"REPLACE INTO `" << it->table() << "` (" <<
						it->field_list() << ") VALUES (";
				}
				else {
					MYSQLPP_QUERY_THISPTR << ",(";
				}

				MYSQLPP_QUERY_THISPTR << it->value_list() << ')';

				empty = false;
			}
			else {
				// Execute what we've built up already, if there is anything
				if (!empty) {
					if (!exec()) {
						success = false;
						break;
					}

					empty = true;
				}

				// If we _still_ can't add, the policy is too strict
				if (policy.can_add(int(tellp()), *it)) {
					MYSQLPP_QUERY_THISPTR << std::setprecision(16) <<
						"REPLACE INTO `" << it->table() << "` (" <<
						it->field_list() << ") VALUES (" <<
						it->value_list() << ')';

					empty = false;
				}
				else {
					// At this point all we can do is give up
					if (throw_exceptions()) {
						throw BadInsertPolicy("Insert policy is too strict");
					}

					success = false;
					break;
				}
			}
		}

		// We might need to execute the last query here.
		if (success && !empty && !exec()) {
			success = false;
		}

		if (success) {
			ac.commit();
		}
		else {
			ac.rollback();
		}

		return *this;
	}

	/// \brief Insert new row unless there is an existing row that
	/// matches on a unique index, in which case we replace it.
	///
	/// This function builds a REPLACE SQL query.  One uses it with
	/// MySQL++'s Specialized SQL Structures mechanism.
	///
	/// \param v new row
	///
	/// \sa insert(), update()
	template <class T>
	Query& replace(const T& v)
	{
		reset();

		MYSQLPP_QUERY_THISPTR << std::setprecision(16) <<
				"REPLACE INTO `" << v.table() << "` (" <<
				v.field_list() << ") VALUES (" << v.value_list() << ')';
		return *this;
	}

	/// \brief Insert multiple new rows, or replace existing ones if
	/// there are existing rows that match on key fields.
	///
	/// Builds a REPLACE SQL query using items from a range within an
	/// STL container.  Insert the entire contents of the container by
	/// using the begin() and end() iterators of the container as
	/// parameters to this function.
	///
	/// \param first iterator pointing to first element in range to
	///    insert/replace
	/// \param last iterator pointing to one past the last element to
	///    insert/replace
	///
	/// \sa insertfrom(), replace(), update()
	template <class Iter>
	Query& replace(Iter first, Iter last)
	{
		reset();
		if (first != last) {
			// Build SQL for first item in the container.  It's special
			// because we need the table name and field list.
			MYSQLPP_QUERY_THISPTR << std::setprecision(16) <<
					"REPLACE INTO " << first->table() << " (" <<
					first->field_list() << ") VALUES (" <<
					first->value_list() << ')';

			// Now insert any remaining container elements.  Be careful
			// hacking on the iterator use here: we want it to work
			// with containers providing only a forward iterator.
			Iter it = first;
			while (++it != last) {
				MYSQLPP_QUERY_THISPTR << ",(" << it->value_list() << ')';
			}
		}

		return *this;
	}	

#if !defined(DOXYGEN_IGNORE)
	// Declare the remaining overloads.  These are hidden down here partly
	// to keep the above code clear, but also so that we may hide them
	// from Doxygen, which gets confused by macro instantiations that look
	// like method declarations.
	mysql_query_define0(std::string, str)
	mysql_query_define0(SimpleResult, execute)
	mysql_query_define0(StoreQueryResult, store)
	mysql_query_define0(UseQueryResult, use)
	mysql_query_define1(storein_sequence)
	mysql_query_define1(storein_set)
	mysql_query_define1(storein)
#endif // !defined(DOXYGEN_IGNORE)

	/// \brief The default template parameters
	///
	/// Used for filling in parameterized queries.
	SQLQueryParms template_defaults;

private:
	friend class SQLQueryParms;

	/// \brief Connection to send queries through
	Connection* conn_;

	/// \brief If true, last query succeeded
	bool copacetic_;

	/// \brief List of template query parameters
	std::vector<SQLParseElement> parse_elems_;

	/// \brief Maps template parameter position values to the
	/// corresponding parameter name.
	std::vector<std::string> parsed_names_;

	/// \brief Maps template parameter names to their position value.
	std::map<std::string, short int> parsed_nums_;

	/// \brief String buffer for storing assembled query
	std::stringbuf sbuffer_;

	/// \brief Process a parameterized query list.
	void proc(SQLQueryParms& p);

	SQLTypeAdapter* pprepare(char option, SQLTypeAdapter& S, bool replace = true);
};


/// \brief Insert raw query string into the given stream.
///
/// This is just syntactic sugar for Query::str(void)
inline std::ostream& operator <<(std::ostream& os, Query& q)
{
	return os << q.str();
}


} // end namespace mysqlpp

#endif // !defined(MYSQLPP_QUERY_H)

<
<
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<

<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
|
<
<
<
<
<
|
<
<
<
<
<
|
<
<
<
|
<
<
<
<
<
<
<
<
<
<
<
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<

<
<
<
<
<
<
<
<
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<

<
<
<
<
<
<
<
<
<
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
|
<
<
<
<
<
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<

<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
|
<
|
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
|
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
|
<
<
<
<
<
<
<
<
<
<
<
<
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
|
<
<
<
<
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
|
<
<
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
|
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<

<
<
<
<
<
<
<
<
<
|
<
<
|
<
<
<
<
<
<
|
<
|
<
<
<
<
<
|
<
<
<
<
<
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<


1





































































































































































2























3





4





5



6











7


































8








9



















































































10









11

















12





13


































































































































14




















15

16
17

















18






















































































































19
20



























21












22





















23











































































































24




25















26




















27


28


























































































































29
30

















31


















































































































































32









33


34






35

36





37





38








































































































































- Change version number in configure.ac and mysql++.bkl.





























































































































































































  All other places the version number occurs are generated files





  created from one of these two.  If there's a corresponding *.in file





  for the one you're looking at, the version number was substituted in



  by autoconf from configure.ac.  Otherwise, the file was most likely











  created by the build system using the version number in mysql++.bkl.











































- Run "make abicheck".  There should be no changes.





























































































  You may have to run the following command in the current "stable"

















  directory before this will succeed, since it depends on there being





  an ACC dump file in place already.























































































































































      $ abi-compliance-checker -lib mysqlpp -dump abi.xml


  ("Stable" is assumed to be in ../3.1.0 relative to the svn "head"

















  checkout, as I write this.)























































































































  This dependence on an existing ABI dump file is deemed reasonable



























  since the ABI of the stable version had better not be changing!












  Plus, it saves some processing time, since ACC can load the stable





















  ABI info without re-parsing its headers and library file.
















































































































- Re-bootstrap the system in pedantic mode, then do a clean rebuild.















  Fix any new errors and warnings.























  Known bogus warnings:



























































































































  - Query's std::basic_ios<> base class is not being initialized.

















    Yes, we know.  We don't care.




























































































































































  - The "==" float comparisons in lib/stadapter.cpp are harmless.


    They're comparisons against special NaN and infinity constants.






    Those are safe.







- Re-bootstrap it again without "pedantic", to avoid shipping the





  pedantic build files.






































































































































Changes to lib/querydef.pl.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
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
56



57






58
59
60
61







62
63
64
65
66

67
68
69
70

71









72
73
74
75
76
77




78
79


80
81
82
83
84
85
86
87

88
89






90
91


92
93
94
95

96
97
98

99
#!/usr/bin/perl -w

########################################################################
# querydef.pl - Generates querydef.h, which defines a number of macros
#	used in query.h that differ only in the number of arguments.  That
#	number limits the number of parameters a MySQL++ template query can
#	accept.  This value can be changed from its default, below.
#
# Copyright (c) 2006-2010 by Educational Technology Resources, Inc.
# Others may also hold copyrights on code in this file.  See the CREDITS
# file in the top directory of the distribution for details.
#
# This file is part of MySQL++.
#
# MySQL++ is free software; you can redistribute it and/or modify it
# under the terms of the GNU Lesser General Public License as published
# by the Free Software Foundation; either version 2.1 of the License, or
# (at your option) any later version.
#
# MySQL++ is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
# License for more details.
#
# You should have received a copy of the GNU Lesser General Public
# License along with MySQL++; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
# USA

########################################################################


















# The number of parameters a template query can accept.  Make this value





# larger only at need, as it adds code to the library proportionally.
# You should not reduce this value if programs you did not write may
# link to the library, as that would constitute an ABI breakage.



my $max_parameters = 25;




# No user-serviceable parts below.



use strict;



use Getopt::Std;




our $opt_f;
getopts('f:') or die "usage: $0 [-f fields]\n\n";
$max_parameters = int($opt_f) if defined $opt_f;




open (OUT, ">querydef.h");


print OUT << "---";
// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
// This file is generated by the Perl script querydef.pl. Please do 
// not modify this file directly. Change the script instead.
// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!






#ifndef MYSQLPP_QUERYDEF_H



#define MYSQLPP_QUERYDEF_H







#define MYSQLPP_TQUERY_MAX_PARAMETERS $max_parameters

---








## Build mysql_query_define0 macro
print OUT "#define mysql_query_define0(RETURN, FUNC) \\\n";
for (my $i = 1; $i < $max_parameters; ++$i) {
	print OUT "\tRETURN FUNC(";

	for (my $j = 0; $j < $i + 1; ++$j) {
		print OUT 'const SQLTypeAdapter& arg', $j;
		print OUT ', ' unless $j == $i;
	}

	print OUT ") \\\n";










	print OUT "\t\t{ return FUNC(SQLQueryParms()";
	for (my $j = 0; $j < $i + 1; ++$j) {
		print OUT ' << arg', $j;
	}
	print OUT "); } \\\n";




}
print OUT "\n";



## Add mysql_query_define1 macro
print OUT "#define mysql_query_define1(FUNC) \\\n";
for (my $i = 1; $i < $max_parameters; ++$i) {
	print OUT "\ttemplate <class T> void FUNC(T& container";
	for (my $j = 0; $j < $i + 1; ++$j) {
		print OUT ', const SQLTypeAdapter& arg', $j;
	}

	print OUT ") \\\n";
	print OUT "\t\t{ FUNC(container, SQLQueryParms()";






	for (my $j = 0; $j < $i + 1; ++$j) {
		print OUT ' << arg', $j;


	}
	print OUT "); } \\\n";
}
print OUT "\n";


## That's all, folks!
print OUT "#endif // !defined(MYSQLPP_QUERYDEF_H)\n";


<
|
<
<
<
|
<
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

>

|
>
>
>
>
>
|
<
<
>
>
>
|
>
>
|
|
|
>
>
|
|
>
>
>
|
>
|
>
>
|
|
<
>
>
>
|
|
|
>
|
<
|
|
|
>
>
>
>
>
|
|
>
>
>
|
>
>
>
>
>
>
|
<
|
<
>
>
>
>
>
>
>
|
|
<
<
<
>
|
<
<
|
>
|
>
>
>
>
>
>
>
>
>
|
<
<
<
|
<
>
>
>
>
|
|
>
>
|
<
<
<
<
<
<
|
>
|
<
>
>
>
>
>
>
|
<
>
>
|
<
|
|
>
|
|
|
>


1



2

3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
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
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73

74
75
76
77
78
79
80
81

82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102

103

104
105
106
107
108
109
110
111
112



113
114


115
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
144
145
146
147

148
149
150

151
152
153
154
155
156
157
158

/***********************************************************************



 tcp_connection.cpp - Implements the TCPConnection class.


 Copyright (c) 2007-2008 by Educational Technology Resources, Inc.
 Others may also hold copyrights on code in this file.  See the
 CREDITS file in the top directory of the distribution for details.

 This file is part of MySQL++.

 MySQL++ is free software; you can redistribute it and/or modify it
 under the terms of the GNU Lesser General Public License as published
 by the Free Software Foundation; either version 2.1 of the License, or
 (at your option) any later version.

 MySQL++ is distributed in the hope that it will be useful, but WITHOUT
 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
 License for more details.

 You should have received a copy of the GNU Lesser General Public
 License along with MySQL++; if not, write to the Free Software
 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
 USA
***********************************************************************/

#define MYSQLPP_NOT_HEADER
#include "common.h"
#include "tcp_connection.h"

#include "exceptions.h"

#if !defined(MYSQLPP_PLATFORM_WINDOWS)
#	include <netdb.h>
#endif

#include <ctype.h>
#include <stdlib.h>
#include <climits>

using namespace std;

namespace mysqlpp {


bool
TCPConnection::connect(const char* addr, const char* db,
		const char* user, const char* pass)
{
	error_message_.clear();



	unsigned int port = 0;
	string address;
	if (addr) {
		address = addr;
		if (!parse_address(address, port, error_message_)) {
			return false;
		}
	}

	if (error_message_.empty()) {
		return Connection::connect(db, address.c_str(), user, pass, port);
	}
	else {
		if (throw_exceptions()) {
			throw ConnectionFailed(error_message_.c_str());
		}
		else {
			return false;
		}
	}
}



bool
TCPConnection::parse_address(std::string& addr, unsigned int& port,
		std::string& error)
{
	error.clear();
	
	// Pull off service name or port number, if any
	string service;

	if (addr[0] == '[') {
		// Might be IPv6 address plus port/service in RFC 2732 form.
		string::size_type pos = addr.find(']');
		if ((pos == string::npos) ||
				(addr.find(':', pos + 1) != (pos + 1)) ||
				(addr.find_first_of("[]", pos + 2) != string::npos)) {
			error = "Malformed IPv6 [address]:service combination";
			return false;
		}

		// We can separate address from port/service now
		service = addr.substr(pos + 2);
		addr = addr.substr(1, pos - 1);

		// Ensure that address part is empty or has at least two colons
		if (addr.size() &&
				(((pos = addr.find(':')) == string::npos) ||
				(addr.find(':', pos + 1) == string::npos))) {
			error = "IPv6 literal needs at least two colons";
			return false;
		}

	}

	else {
		// Can only be IPv4 address, so check for 0-1 colons
		string::size_type pos = addr.find(':');
		if (pos != string::npos) {
			if (addr.find(':', pos + 1) != string::npos) {
				error = "IPv4 address:service combo can have only one colon";
				return false;
			}
			



			service = addr.substr(pos + 1);
			addr = addr.substr(0, pos);


		}
	}

	// Turn service into a port number, if it was given.  If not, don't
	// overwrite port because it could have a legal value passed in from
	// Connection.
	if (!service.empty()) {
		if (isdigit(service[0])) {
			port = atoi(service.c_str());
			if ((port < 1) || (port > USHRT_MAX)) {
				error = "Invalid TCP port number " + service;
				return false;
			}



		}

		else {
			servent* pse = getservbyname(service.c_str(), "tcp");
			if (pse) {
				port = ntohs(pse->s_port);
			}
			else {
				error = "Failed to look up TCP service " + service;
				return false;
			}






		}
	}


	// Ensure that there are only alphanumeric characters, dots,
	// dashes and colons in address.  Anything else must be an error.
	for (string::const_iterator it = addr.begin(); it != addr.end(); ++it) {
		string::value_type c = *it;
		if (!(isalnum(c) || (c == '.') || (c == '-') || (c == ':'))) {
			error = "Bad character '";
			error += c;

			error += "' in TCP/IP address";
			return false;
		}

	}

	return true;
}


} // end namespace mysqlpp

Changes to lib/result.cpp.

1
2
3
4
5
6

7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
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
56
57

58
59
60

61
62
63
64
65
66
67
68
69
70
71
72
73
74
75



76
77
78
79
80




81
82
83

84
85
86
87
88
89
90
91
92
93
94



95
96
97

98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
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
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




191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
/***********************************************************************
 result.cpp - Implements the ResultBase, StoreQueryResult and
	UseQuery Result classes.

 Copyright (c) 1998 by Kevin Atkinson, (c) 1999-2001 by MySQL AB, and
 (c) 2004-2007 by Educational Technology Resources, Inc.  Others may

 also hold copyrights on code in this file.  See the CREDITS.txt file
 in the top directory of the distribution for details.

 This file is part of MySQL++.

 MySQL++ is free software; you can redistribute it and/or modify it
 under the terms of the GNU Lesser General Public License as published
 by the Free Software Foundation; either version 2.1 of the License, or
 (at your option) any later version.

 MySQL++ is distributed in the hope that it will be useful, but WITHOUT
 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
 License for more details.

 You should have received a copy of the GNU Lesser General Public
 License along with MySQL++; if not, write to the Free Software
 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
 USA
***********************************************************************/

#include "result.h"

#include "dbdriver.h"




namespace mysqlpp {


ResultBase::ResultBase(MYSQL_RES* res, DBDriver* dbd, bool te) :
OptionalExceptions(te),
driver_(res ? dbd : 0),
fields_(Fields::size_type(res ? dbd->num_fields(res) : 0)),
current_field_(0)
{
	if (res) {


		Fields::size_type i = 0;
		const MYSQL_FIELD* pf;
		while ((i < fields_.size()) && (pf = dbd->fetch_field(res))) {
			fields_[i++] = pf;
		}
		dbd->field_seek(res, 0);		// semantics break otherwise!

		names_ = new FieldNames(this);
		types_ = new FieldTypes(this);
	}
}








ResultBase&
ResultBase::copy(const ResultBase& other)

{
	if (this != &other) {
		set_exceptions(other.throw_exceptions());


		if (other.driver_) {
			driver_ = other.driver_;
			fields_ = other.fields_;
			names_ = other.names_;
			types_ = other.types_;
			current_field_ = other.current_field_;
		}
		else {
			driver_ = 0;
			fields_.clear();
			names_ = 0;
			types_ = 0;
			current_field_ = 0;
		}



	}

	return *this;
}






int
ResultBase::field_num(const std::string& i) const

{
	size_t index = (*names_)[i];
	if ((index >= names_->size()) && throw_exceptions()) {
		if (throw_exceptions()) {
			throw BadFieldName(i.c_str());
		}
		else {
			return -1;
		}
	}
	



	return int(index);
}



StoreQueryResult::StoreQueryResult(MYSQL_RES* res, DBDriver* dbd,
		bool te) :
ResultBase(res, dbd, te),
list_type(list_type::size_type(res && dbd ? dbd->num_rows(res) : 0)),
copacetic_(res && dbd)
{
	if (copacetic_) {
		iterator it = begin();
		while (MYSQL_ROW row = dbd->fetch_row(res)) {
			if (const unsigned long* lengths = dbd->fetch_lengths(res)) {
				*it = Row(row, this, lengths, throw_exceptions());
				++it;
			}
		}

		dbd->free_result(res);
	}
}






StoreQueryResult&
StoreQueryResult::copy(const StoreQueryResult& other)
{
	if (this != &other) {
		ResultBase::copy(other);
		assign(other.begin(), other.end());
		copacetic_ = other.copacetic_;
	}


	return *this;
}



UseQueryResult::UseQueryResult(MYSQL_RES* res, DBDriver* dbd, bool te) :
ResultBase(res, dbd, te)
{
	if (res) {
		result_ = res;
	}
}



UseQueryResult&
UseQueryResult::copy(const UseQueryResult& other)

{
	if (this != &other) {
		ResultBase::copy(other);

		if (other.result_) {
			result_ = other.result_;
		}
		else {
			result_ = 0;
		}
	}


	return *this;
}


const unsigned long*
UseQueryResult::fetch_lengths() const
{
	return driver_->fetch_lengths(result_.raw());
}



Row
UseQueryResult::fetch_row() const
{
	if (!result_) {
		if (throw_exceptions()) {
			throw UseQueryError("Results not fetched");
		}


		else {

			return Row();
		}
	}

	MYSQL_ROW row = driver_->fetch_row(result_.raw());
	if (row) {
		const unsigned long* lengths = fetch_lengths();
		if (lengths) {
			return Row(row, this, lengths, throw_exceptions());
		}
		else {
			if (throw_exceptions()) {
				throw UseQueryError("Failed to get field lengths");
			}
			else {
				return Row();
			}


		}




	}
	else {
		// Prior to v3, this was considered an error, but it just means
		// we've fallen off the end of a "use" query's result set.  You
		// can't predict when this will happen, but it isn't an error.
		// Just return a falsy row object so caller's loop terminates.
		return Row();
	}
}


MYSQL_ROW
UseQueryResult::fetch_raw_row() const
{
	return driver_->fetch_row(result_.raw());
}


} // end namespace mysqlpp


|
<

<
|
>
|
|



















|

|

>
>




<
<
|
<
|
<
<
>
>
|
<
<
<
<
<
|
<
<
|
<
>
>
|
>
>
>
>
|
<
<
>
|
<
<
>
|
<
|
<
<
<
<
|
<
<
<
<
<
<
|
>
>
>
|

<
|

>
>
>
>

|
<
>

<
<
<
|
<
<
<
<
<
|
>
>
>
|
<
|
>
|
<
<
|
<
<
<
<
<
<
<
<
|
|
|
|
<
|
|
>
>
>
>

|
|
<

<
<
|
<
<
|
>
|
|
|
>
|
<
<
<
<
<
|
|

>

<
|
>

<
|
>
|
|
|
|
<
<
<
|
>
|
|
|
<
<
<
<
<
|

>

|
|

|
<
<
|
>
>
|
>
|


|
<
<
<
<
<
<
<
<
<
|
<
<
|
>
>
|
>
>
>
>
|
<
|
|
|
<
<
<
<
|
|
<
<
<
<





1
2

3

4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
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

56




57






58
59
60
61
62
63

64
65
66
67
68
69
70
71

72
73



74





75
76
77
78
79

80
81
82


83








84
85
86
87

88
89
90
91
92
93
94
95
96

97


98


99
100
101
102
103
104
105





106
107
108
109
110

111
112
113

114
115
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
144
145
146
147
148
149
150
151

152
153
154




155
156




157
158
159
160
161
/***********************************************************************
 cpool.cpp - Implements the ConnectionPool class.



 Copyright (c) 2007 by Educational Technology Resources, Inc. and
 (c) 2007 by Jonathan Wakely.  Others may also hold copyrights on
 code in this file.  See the CREDITS.txt file in the top directory
 of the distribution for details.

 This file is part of MySQL++.

 MySQL++ is free software; you can redistribute it and/or modify it
 under the terms of the GNU Lesser General Public License as published
 by the Free Software Foundation; either version 2.1 of the License, or
 (at your option) any later version.

 MySQL++ is distributed in the hope that it will be useful, but WITHOUT
 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
 License for more details.

 You should have received a copy of the GNU Lesser General Public
 License along with MySQL++; if not, write to the Free Software
 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
 USA
***********************************************************************/

#include "cpool.h"

#include "connection.h"

#include <algorithm>
#include <functional>

namespace mysqlpp {




/// \brief Functor to test whether a given ConnectionInfo object is

/// "too old".


///
/// \internal This is a template only because ConnectionInfo is private.
/// Making it a template means the private type is only used at the point





/// of instantiation, where it is accessible.




template <typename ConnInfoT>
class TooOld : std::unary_function<ConnInfoT, bool>
{
public:
#if !defined(DOXYGEN_IGNORE)
	TooOld(unsigned int tmax) :
	min_age_(time(0) - tmax)
	{


	}



	bool operator()(const ConnInfoT& conn_info) const
	{

		return !conn_info.in_use && conn_info.last_used <= min_age_;




	}







#endif
private:
	time_t min_age_;
};




//// clear /////////////////////////////////////////////////////////////
// Destroy connections in the pool, either all of them (completely
// draining the pool) or just those not currently in use.  The public
// method shrink() is an alias for clear(false).

void

ConnectionPool::clear(bool all)
{



	ScopedLock lock(mutex_);	// ensure we're not interfered with






	PoolIt it = pool_.begin(), doomed;
	while (it != pool_.end()) {
		if (all || !it->in_use) {
			doomed = it++;

			destroy(doomed->conn);
			pool_.erase(doomed);
		}


		else {








			++it;
		}
	}
}



//// find_mru //////////////////////////////////////////////////////////
// Find most recently used available connection.  Uses operator< for
// ConnectionInfo to order pool with MRU connection last.  Returns 0 if
// there are no connections not in use.

Connection*
ConnectionPool::find_mru()

{


	PoolIt mru = std::max_element(pool_.begin(), pool_.end());


	if (mru != pool_.end() && !mru->in_use) {
		mru->in_use = true;
		return mru->conn;
	}
	else {
		return 0;
	}





}


//// grab //////////////////////////////////////////////////////////////


Connection*
ConnectionPool::grab()
{

	ScopedLock lock(mutex_);	// ensure we're not interfered with
	remove_old_connections();
	if (Connection* mru = find_mru()) {
		return mru;
	}
	else {



		// No free connections, so create and return a new one.
		pool_.push_back(ConnectionInfo(create()));
		return pool_.back().conn;
	}
}







//// release ///////////////////////////////////////////////////////////

void
ConnectionPool::release(const Connection* pc)
{
	ScopedLock lock(mutex_);	// ensure we're not interfered with



	for (PoolIt it = pool_.begin(); it != pool_.end(); ++it) {
		if (it->conn == pc) {
			it->in_use = false;
			it->last_used = time(0);
			break;
		}
	}
}













//// remove_old_connections ////////////////////////////////////////////
// Remove connections that were last used too long ago.

void
ConnectionPool::remove_old_connections()
{
	TooOld<ConnectionInfo> too_old(max_idle_time());


	PoolIt it = pool_.begin();
	while ((it = std::find_if(it, pool_.end(), too_old)) != pool_.end()) {
		destroy(it->conn);




		pool_.erase(it++);
	}




}


} // end namespace mysqlpp

Changes to lib/result.h.

1
2
3
4
5
6
7
8
9

10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
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
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
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
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
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
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
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
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
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
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
/// \file result.h
/// \brief Declares classes for holding information about SQL query
/// results.

/***********************************************************************
 Copyright (c) 1998 by Kevin Atkinson, (c) 1999-2001 by MySQL AB, and
 (c) 2004-2007 by Educational Technology Resources, Inc.  Others may
 also hold copyrights on code in this file.  See the CREDITS.txt file
 in the top directory of the distribution for details.


 This file is part of MySQL++.

 MySQL++ is free software; you can redistribute it and/or modify it
 under the terms of the GNU Lesser General Public License as published
 by the Free Software Foundation; either version 2.1 of the License, or
 (at your option) any later version.

 MySQL++ is distributed in the hope that it will be useful, but WITHOUT
 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
 License for more details.

 You should have received a copy of the GNU Lesser General Public
 License along with MySQL++; if not, write to the Free Software
 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
 USA
***********************************************************************/

#if !defined(MYSQLPP_RESULT_H)
#define MYSQLPP_RESULT_H

#include "common.h"

#include "exceptions.h"
#include "field.h"
#include "field_names.h"
#include "field_types.h"
#include "noexceptions.h"
#include "refcounted.h"
#include "row.h"

namespace mysqlpp {


/// \brief Holds information about the result of queries that don't
/// return rows.

class MYSQLPP_EXPORT SimpleResult
{
private:
	/// \brief Pointer to bool data member, for use by safe bool
	/// conversion operator.
	///
	/// \see http://www.artima.com/cppsource/safebool.html
	typedef bool SimpleResult::*private_bool_type;

public:
	/// \brief Default ctor
	SimpleResult() :
	copacetic_(false),
	insert_id_(0),
	rows_(0)
	{
	}

	/// \brief Initialize object
	SimpleResult(bool copacetic, ulonglong insert_id,
			ulonglong rows, const std::string& info) :
	copacetic_(copacetic),
	insert_id_(insert_id),
	rows_(rows),
	info_(info)
	{
	}

	/// \brief Test whether the query that created this result succeeded
	///
	/// If you test this object in bool context and it's false, it's a
	/// signal that the query this was created from failed in some way.
	/// Call Query::error() or Query::errnum() to find out what exactly
	/// happened.
	operator private_bool_type() const
	{
		return copacetic_ ? &SimpleResult::copacetic_ : 0;
	}

	/// \brief Get the last value used for an AUTO_INCREMENT field
	ulonglong insert_id() const { return insert_id_; }

	/// \brief Get the number of rows affected by the query
	ulonglong rows() const { return rows_; }

	/// \brief Get any additional information about the query returned
	/// by the server.
	const char* info() const { return info_.c_str(); }

private:
	bool copacetic_;
	ulonglong insert_id_;
	ulonglong rows_;
	std::string info_;
};


/// \brief Base class for StoreQueryResult and UseQueryResult.
///
/// Not useful directly.  Just contains common functionality for its
/// subclasses.

class MYSQLPP_EXPORT ResultBase : public OptionalExceptions
{
public:
	/// \brief Destroy object
	virtual ~ResultBase() { }

	/// \brief Returns the next field in this result set
	const Field& fetch_field() const
			{ return fields_.at(current_field_++); }

	/// \brief Returns the given field in this result set
	const Field& fetch_field(Fields::size_type i) const
			{ return fields_.at(i); }

	/// \brief Get the underlying Field structure given its index.
	const Field& field(unsigned int i) const { return fields_.at(i); }

	/// \brief Get the underlying Fields structure.
	const Fields& fields() const { return fields_; }

	/// \brief Get the name of the field at the given index.
	const std::string& field_name(int i) const
			{ return names_->at(i); }

	/// \brief Get the names of the fields within this result set.
	const RefCountedPointer<FieldNames>& field_names() const
			{ return names_; }

	/// \brief Get the index of the named field.
	///
	/// This is the inverse of field_name().
	int field_num(const std::string&) const;

	/// \brief Get the type of a particular field within this result set.
	const FieldTypes::value_type& field_type(int i) const
			{ return types_->at(i); }

	/// \brief Get a list of the types of the fields within this
	/// result set.
	const RefCountedPointer<FieldTypes>& field_types() const
			{ return types_; }

	/// \brief Returns the number of fields in this result set
	size_t num_fields() const { return fields_.size(); }

	/// \brief Return the name of the table the result set comes from
	const char* table() const
			{ return fields_.empty() ? "" : fields_[0].table(); }

protected:
	/// \brief Create empty object
	ResultBase() :
	driver_(0),
	current_field_(0)
	{
	}
	
	/// \brief Create the object, fully initialized
	ResultBase(MYSQL_RES* result, DBDriver* dbd, bool te = true);
	
	/// \brief Create object as a copy of another ResultBase
	ResultBase(const ResultBase& other) :
	OptionalExceptions()
	{
		copy(other);
	}

	/// \brief Copy another ResultBase object's contents into this one.
	ResultBase& copy(const ResultBase& other);

	DBDriver* driver_;	///< Access to DB driver; fully initted if nonzero
	Fields fields_;		///< list of fields in result

	/// \brief list of field names in result
	RefCountedPointer<FieldNames> names_;

	/// \brief list of field types in result
	RefCountedPointer<FieldTypes> types_;

	/// \brief Default field index used by fetch_field()
	///
	/// It's mutable because it's just internal housekeeping: it's
	/// changed by fetch_field(void), but it doesn't change the "value"
	/// of the result.  See mutability justification for
	/// UseQueryResult::result_: this field provides functionality we
	/// used to get through result_, so it's relevant here, too.
	mutable Fields::size_type current_field_;
};


/// \brief StoreQueryResult set type for "store" queries
///
/// This is the obvious C++ implementation of a class to hold results 
/// from a SQL query that returns rows: a specialization of std::vector
/// holding Row objects in memory so you get random-access semantics.
/// MySQL++ also supports UseQueryResult which is less friendly, but has
/// better memory performance.  See the user manual for more details on
/// the distinction and the usage patterns required.

class MYSQLPP_EXPORT StoreQueryResult :
		public ResultBase,
		public std::vector<Row>
{
private:
	/// \brief Pointer to bool data member, for use by safe bool
	/// conversion operator.
	///
	/// \see http://www.artima.com/cppsource/safebool.html
	typedef bool StoreQueryResult::*private_bool_type;

public:
	typedef std::vector<Row> list_type;	///< type of vector base class

	/// \brief Default constructor
	StoreQueryResult() :
	ResultBase(),
	copacetic_(false)
	{
	}
	
	/// \brief Fully initialize object
	StoreQueryResult(MYSQL_RES* result, DBDriver* dbd, bool te = true);

	/// \brief Initialize object as a copy of another StoreQueryResult
	/// object
	StoreQueryResult(const StoreQueryResult& other) :
	ResultBase(),
	std::vector<Row>(),
	copacetic_(false)
	{
		copy(other);
	}

	/// \brief Destroy result set
	~StoreQueryResult() { }

	/// \brief Returns the number of rows in this result set
	list_type::size_type num_rows() const { return size(); }

	/// \brief Copy another StoreQueryResult object's data into this
	/// object
	StoreQueryResult& operator =(const StoreQueryResult& rhs)
			{ return this != &rhs ? copy(rhs) : *this; }

	/// \brief Test whether the query that created this result succeeded
	///
	/// If you test this object in bool context and it's false, it's a
	/// signal that the query this was created from failed in some way.
	/// Call Query::error() or Query::errnum() to find out what exactly
	/// happened.
	operator private_bool_type() const
	{
		return copacetic_ ? &StoreQueryResult::copacetic_ : 0;
	}

private:
	/// \brief Copy another StoreQueryResult object's contents into this
	/// one.
	StoreQueryResult& copy(const StoreQueryResult& other);

	bool copacetic_;	///< true if initialized from a good result set
};


/// \brief Functor to call mysql_free_result() on the pointer you pass
/// to it.
///
/// This overrides RefCountedPointer's default destroyer, which uses
/// operator delete; it annoys the C API when you nuke its data
/// structures this way. :)
template <>
struct RefCountedPointerDestroyer<MYSQL_RES>
{
	/// \brief Functor implementation
	void operator()(MYSQL_RES* doomed) const
	{
		if (doomed) {
			mysql_free_result(doomed);
		}
	}
};


/// \brief StoreQueryResult set type for "use" queries
///
/// See the user manual for the reason you might want to use this even
/// though its interface is less friendly than StoreQueryResult's.

class MYSQLPP_EXPORT UseQueryResult : public ResultBase
{
public:
	/// \brief Default constructor
	UseQueryResult() :
	ResultBase()
	{
	}
	
	/// \brief Create the object, fully initialized
	UseQueryResult(MYSQL_RES* result, DBDriver* dbd, bool te = true);
	
	/// \brief Create a copy of another UseQueryResult object
	UseQueryResult(const UseQueryResult& other) :
	ResultBase()
	{
		copy(other);
	}
	
	/// \brief Destroy object
	~UseQueryResult() { }

	/// \brief Copy another UseQueryResult object's data into this object
	UseQueryResult& operator =(const UseQueryResult& rhs)
			{ return this != &rhs ? copy(rhs) : *this; }

	/// \brief Returns the next field in this result set
	const Field& fetch_field() const
			{ return fields_.at(current_field_++); }

	/// \brief Returns the given field in this result set
	const Field& fetch_field(Fields::size_type i) const




			{ return fields_.at(i); }

	/// \brief Returns the lengths of the fields in the current row of
	/// the result set.
	///
	/// \internal This should not be terribly useful to end-user code.
	/// The Row object returned by fetch_row() contains these lengths.
	const unsigned long* fetch_lengths() const;

	/// \brief Returns the next row in a "use" query's result set
	///
	/// This is a thick wrapper around DBDriver::fetch_row().  It does a
	/// lot of error checking before returning the Row object containing
	/// the row data.
	///
	/// \sa fetch_raw_row()
	Row fetch_row() const;

	/// \brief Wraps mysql_fetch_row() in MySQL C API.
	///
	/// \internal You almost certainly want to call fetch_row() instead.
	/// It is anticipated that this is only useful within the library,
	/// to implement higher-level query types on top of raw "use"
	/// queries. Query::storein() uses it, for example.
	MYSQL_ROW fetch_raw_row() const;

	/// \brief Jumps to the given field within the result set
	///
	/// Calling this allows you to reset the default field index used
	/// by fetch_field().
	void field_seek(Fields::size_type field) const
			{ current_field_ = field; }

	/// \brief Return the pointer to the underlying MySQL C API
	/// result set object.
	///
	/// While this has obvious inherent value for those times you need
	/// to dig beneath the MySQL++ interface, it has subtler value.
	/// It effectively stands in for operator bool(), operator !(),
	/// operator ==(), and operator !=(), because the C++ compiler can
	/// implement all of these with a MYSQL_RES*.
	///
	/// Of these uses, the most valuable is using the UseQueryResult
	/// object in bool context to determine if the query that created
	// it was successful:
	///
	/// \code
	///   Query q("....");
	///   if (UseQueryResult res = q.use()) {
	///       // Can use 'res', query succeeded
	///   }
	///   else {
	///       // Query failed, call Query::error() or ::errnum() for why
	///   }
	/// \endcode
	operator MYSQL_RES*() const { return result_.raw(); }
	
private:
	/// \brief Copy another ResultBase object's contents into this one.
	UseQueryResult& copy(const UseQueryResult& other);

	/// \brief Reference to underlying C API result set
	///
	/// This is mutable because so many methods in this class are
	/// are justifiably const because they don't modify the result
	/// set's "value" but they call C API methods that take non-const
	/// MYSQL_RES* so they can only be const if this is mutable.  It's
	/// quite likely that these API functions do modify the MYSQL_RES
	/// object, so strict constness says this object changed, too, but
	/// this has always been mutable and the resulting behavior hasn't 
	/// confused anyone yet.
	mutable RefCountedPointer<MYSQL_RES> result_;
};


/// \brief Swaps two StoreQueryResult objects
inline void
swap(StoreQueryResult& x, StoreQueryResult& y)
{
	StoreQueryResult tmp = x;
	x = y;
	y = tmp;
}

/// \brief Swaps two UseQueryResult objects
inline void
swap(UseQueryResult& x, UseQueryResult& y)
{
	UseQueryResult tmp = x;
	x = y;
	y = tmp;
}

} // end namespace mysqlpp

#endif // !defined(MYSQLPP_RESULT_H)
|
|
|

<
|
|
|
|
>



















<
<
<
|
<
<
|
<
<
<
<
|

<
|
|
<
<

<
<
<
<
<
<
<
<
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
|
<
<
|
<
<
|
<
<
|
<
<
<
|
<
<
<
<
<
<
|
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
|
|
<
<
<
<
<

<
<
<
|
<
<
<
|
<
<
<
<
|
<
<
<

<
<
<
<
|
<
<
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
|
<
<
<
<
<
<
<
|
<
<
<
<
<
<
<
|
<
|
<
<
|
<
<
<
<
<
<
<
<
<
|
<
<
|
<
<
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
|
<
<
<
<
<
<
<
<
|
|
<
<
<
<
|
<
<
<
<
<
<
<

|
<
<
|
<
<
<
<
<
<
|
<
<
<
<
<
<
<
<
<
|
|
<
|
>
>
>
>
|
|
<
<
<
<
<
|
|
<
<
<
<
<
<
<
<
|
<
<
<
<
<
<
<
|
<
<
<
<
<
<
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
|
<
<
<
|
<
<
<
<
<
<
<
<
<
<
<
<
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
1
2
3
4

5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
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

56


57









58


59


60

































61








62
63




64







65
66


67






68









69
70

71
72
73
74
75
76
77





78
79








80







81






82























83



84












85






















/***********************************************************************
 ssqls5.cpp - Example showing how to use the equal_list() member of
	some SSQLS types to build SELECT queries with custom WHERE clauses.


 Copyright (c) 1998 by Kevin Atkinson, (c) 1999-2001 by MySQL AB, (c)
 2004-2008 by Educational Technology Resources, Inc., and (c) 2005 by
 Chris Frey.  Others may also hold copyrights on code in this file.
 See the CREDITS.txt file in the top directory of the distribution
 for details.

 This file is part of MySQL++.

 MySQL++ is free software; you can redistribute it and/or modify it
 under the terms of the GNU Lesser General Public License as published
 by the Free Software Foundation; either version 2.1 of the License, or
 (at your option) any later version.

 MySQL++ is distributed in the hope that it will be useful, but WITHOUT
 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
 License for more details.

 You should have received a copy of the GNU Lesser General Public
 License along with MySQL++; if not, write to the Free Software
 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
 USA
***********************************************************************/




#include "cmdline.h"


#include "printdata.h"




#include "stock.h"


#include <iostream>
#include <vector>











using namespace std;





























int


main(int argc, char *argv[])


{



	// Get database access parameters from command line






	const char* db = 0, *server = 0, *user = 0, *pass = "";
	if (!parse_command_line(argc, argv, &db, &server, &user, &pass)) {

















		return 1;
	}









	try {



		// Establish the connection to the database server.




		mysqlpp::Connection con(db, server, user, pass);








		// Get all the rows in the stock table.


		mysqlpp::Query query = con.query("select * from stock");
























































		vector<stock> res;







		query.storein(res);









		if (res.size() > 0) {


			// Build a select query using the data from the first row









			// returned by our previous query.


			query << "select * from stock where " <<


					res[0].equal_list(" and ", stock_weight, stock_price);










































			// Display the finished query.
			cout << "Custom query:\n" << query << endl;




		}







	}
	catch (const mysqlpp::BadQuery& er) {


		// Handle any query errors






		cerr << "Query error: " << er.what() << endl;









		return -1;
	}

	catch (const mysqlpp::BadConversion& er) {
		// Handle bad conversions
		cerr << "Conversion error: " << er.what() << endl <<
				"\tretrieved data size: " << er.retrieved <<
				", actual size: " << er.actual_size << endl;
		return -1;
	}





	catch (const mysqlpp::Exception& er) {
		// Catch-all for any other MySQL++ exceptions








		cerr << "Error: " << er.what() << endl;







		return -1;






	}



























	return 0;












}






















Changes to lib/row.cpp.

1

2

3
4
5
6
7
8
9


10
11
12
13
14
15
16

17
18
19
20

21
22
23
24
25

26
27
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
56
57
58


59
60




61
62
63
64
65
66
67




68
69
70


71
72
73
74
75
76

77
78
79

80
81
82
83
84
85
86
87
88
89
90
91
92
93
94


95
96
97
98
99
100
101



102
103
104
105
106
107
108
109
110
111
112
113
114



115
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
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
191
192
193

194
195

196
197
198
199
200
201
202
203


204
205
/***********************************************************************

 row.cpp - Implements the Row class.


 Copyright (c) 1998 by Kevin Atkinson, (c) 1999-2001 by MySQL AB, and
 (c) 2004-2007 by Educational Technology Resources, Inc.  Others may
 also hold copyrights on code in this file.  See the CREDITS.txt file
 in the top directory of the distribution for details.

 This file is part of MySQL++.



 MySQL++ is free software; you can redistribute it and/or modify it
 under the terms of the GNU Lesser General Public License as published
 by the Free Software Foundation; either version 2.1 of the License, or
 (at your option) any later version.

 MySQL++ is distributed in the hope that it will be useful, but WITHOUT

 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
 License for more details.


 You should have received a copy of the GNU Lesser General Public
 License along with MySQL++; if not, write to the Free Software
 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
 USA
***********************************************************************/


#include "row.h"



#include "result.h"













namespace mysqlpp {

Row::Row(MYSQL_ROW row, const ResultBase* res,
		const unsigned long* lengths, bool throw_exceptions) :
OptionalExceptions(throw_exceptions),
initialized_(false)
{
	if (row) {
		if (res) {
			size_type size = res->num_fields();
			data_.reserve(size);
			for (size_type i = 0; i < size; ++i) {
				bool is_null = row[i] == 0;
				data_.push_back(value_type(
						is_null ? "NULL" : row[i],
						is_null ? 4 : lengths[i],
						res->field_type(int(i)),
						is_null));
			}



			field_names_ = res->field_names();
			initialized_ = true;
		}

		else if (throw_exceptions) {
			throw ObjectNotInitialized("RES is NULL");
		}
	}


	else if (throw_exceptions) {
		throw ObjectNotInitialized("ROW is NULL");




	}
}


Row::const_reference
Row::at(size_type i) const
{




	if (i < size()) {
		return data_[i];
	}


	else {
		throw BadIndex("Row", int(i), int(size()));
	}
}



equal_list_ba<FieldNames, Row, quote_type0>
Row::equal_list(const char* d, const char* e) const
{

	return equal_list_ba<FieldNames, Row, quote_type0>(
			*field_names_, *this, d, e, quote);
}


template <class Manip>
equal_list_ba<FieldNames, Row, Manip>
Row::equal_list(const char* d, const char* e, Manip m) const
{
	return equal_list_ba<FieldNames, Row, Manip>(
			*field_names_, *this, d, e, m);
}


value_list_ba<FieldNames, do_nothing_type0>


Row::field_list(const char* d) const
{
	return value_list_ba<FieldNames, do_nothing_type0>
			(*field_names_, d, do_nothing);
}





template <class Manip>
value_list_ba<FieldNames, Manip>
Row::field_list(const char *d, Manip m) const
{
	return value_list_ba<FieldNames, Manip>(*field_names_, d, m);
}


template <class Manip>
value_list_b<FieldNames, Manip>
Row::field_list(const char *d, Manip m, const std::vector<bool>& vb) const
{
	return value_list_b<FieldNames, Manip>(*field_names_, vb, d, m);



}




value_list_b<FieldNames, quote_type0>
Row::field_list(const char* d, const std::vector<bool>& vb) const
{
	return value_list_b<FieldNames, quote_type0>(*field_names_,
			vb, d, quote);




}



value_list_b<FieldNames, quote_type0>
Row::field_list(const std::vector<bool>& vb) const
{
	return value_list_b<FieldNames, quote_type0>(*field_names_,


			vb, ",", quote);
}


template <class Manip> value_list_b<FieldNames, Manip>
Row::field_list(const char* d, Manip m, bool t0, bool t1, bool t2,
		bool t3, bool t4, bool t5, bool t6, bool t7, bool t8, bool t9,
		bool ta, bool tb, bool tc) const

{
	std::vector<bool> vb;
	create_vector(field_names_->size(), vb, t0, t1, t2, t3, t4,
			t5, t6, t7, t8, t9, ta, tb, tc);
	return value_list_b<FieldNames, Manip>(*field_names_, vb, d, m);
}


value_list_b<FieldNames, quote_type0>
Row::field_list(const char *d, bool t0, bool t1, bool t2, bool t3,
		bool t4, bool t5, bool t6, bool t7, bool t8, bool t9, bool ta,
		bool tb, bool tc) const
{

	std::vector<bool> vb;
	create_vector(field_names_->size(), vb, t0, t1, t2, t3, t4,
			t5, t6, t7, t8, t9, ta, tb, tc);






	return value_list_b<FieldNames, quote_type0>(*field_names_,
			vb, d, quote);
}



value_list_b<FieldNames, quote_type0>
Row::field_list(bool t0, bool t1, bool t2, bool t3, bool t4, bool t5,
		bool t6, bool t7, bool t8, bool t9, bool ta, bool tb,

		bool tc) const
{


	std::vector<bool> vb;
	create_vector(field_names_->size(), vb, t0, t1, t2, t3, t4,
			t5, t6, t7, t8, t9, ta, tb, tc);
	return value_list_b<FieldNames, quote_type0>(*field_names_,
			vb, ",", quote);
}


Row::size_type
Row::field_num(const char* name) const

{

	if (field_names_) {
		return (*field_names_)[name];


	}
	else if (throw_exceptions()) {
		throw BadFieldName(name);
	}
	else {
		return 0;

	}
}


const Row::value_type&
Row::operator [](const char* field) const
{

	size_type si = field_num(field);
	if (si < size()) {
		return at(si);
	}

	else if (throw_exceptions()) {
		throw BadFieldName(field);

	}
	else {
		static value_type empty;
		return empty;
	}
}




} // end namespace mysqlpp

<
>
|
>

<
|
|
<

|
>
>

<
|
|
<

|
>
|
|
<

>
|
|
|
|
<
>
|
|
|
>
>
|
|
>

>
>
>
>
>
>
>
>
>
>
|
|
<
<
<
|
|
<
<
<
<
<
<
<
<
<
<
<
|
>
>

|
|
<
>
|
|
<
<
>
>
|
|
>
>
>
>
|
<
|
|
|
<
|
>
>
>
>
|
<
<
>
>
|
<
<
<
|
|
>
<
<
|
>
|
<
<
|
|
|
<
<
|
|
<
<
|
|
<
>
>
|
|
|
<
<
|
|
>
>
>
|
<
<
|
|
<
|
|
|
|
<
|
<
>
>
>
|
|
>
>

|
|
|
|
|
>
>
>
>
|
|
>
|
|
|
|
|
>
>
|
|
|
|
<
<
|
|
>
|
<
<
<
<
|
|
|
<
<
<
<
|
>
|
<
<
>
>
>
>
>
>
<
<
|
|
>

|
<
<
>
|
|
>
>
|
<
<
<
<
|
|
|
<
<
>
|
>
|
<
>
>
|
<
<
|
|
|
>
|
<
|
|
|
|
<
>
|
|
|
<
>
|
|
>
|
<
|
|
<
<
|
|
>
>
|
|

1
2
3
4

5
6

7
8
9
10
11

12
13

14
15
16
17
18

19
20
21
22
23
24

25
26
27
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
56
57


58
59
60
61
62
63
64
65
66

67
68
69

70
71
72
73
74
75


76
77
78



79
80
81


82
83
84


85
86
87


88
89


90
91

92
93
94
95
96


97
98
99
100
101
102


103
104

105
106
107
108

109

110
111
112
113
114
115
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
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

191
192
193
194
195

196
197


198
199
200
201
202
203

<?xml version="1.0" encoding='UTF-8'?>
<!DOCTYPE sect1 PUBLIC "-//OASIS//DTD DocBook V4.2//EN"
    "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">


<sect1 id="configuration">
  <title>Configuring MySQL++</title>


  <para>The default configuration of MySQL++ is suitable for most
  purposes, but there are a few things you can change to make it meet
  special needs.</para>


  <sect2 id="mysql-loc">
    <title>The Location of the MySQL Development Files</title>


    <para>MySQL++ is built on top of the MySQL C API. It relies on
    this low-level library for all communication with the database
    server. Consequently, the build process for MySQL++ may fail if
    it can&#x2019;t find the C API headers and library.</para>


    <para>On platforms that use Autoconf<footnote><para>Linux,
    Solaris, the BSDs, Mac OS X command line (as opposed to the
    Xcode IDE), Cygwin... Basically, Unix or anything that works
    like it.</para></footnote>, the <filename>configure</filename>
    script can usually figure out the location of the C API

    development files by itself. It simply tries a bunch of common
    installation locations until it finds one that works. If
    your MySQL server was installed in a nonstandard location,
    you will have to tell the <filename>configure</filename>
    script where these files are with some combination
    of the <computeroutput>--with-mysql</computeroutput>,
    <computeroutput>--with-mysql-include</computeroutput>, and
    <computeroutput>--with-mysql-lib</computeroutput> flags. See
    <filename>README-Unix.txt</filename> for details.</para>

    <para>No other platform allows this sort of auto-discovery,
    so the build files for these platforms simply hard-code the
    default installation location for whatever version of MySQL is
    in GA state at the time that version of MySQL++ was released. For
    example, the Visual C++ project files currently assume MySQL is in
    <filename>c:\Program Files\MySQL\MySQL Server 5.1</filename>. If
    you&#x2019;re using some other release of MySQL or you installed it
    somewhere else, you will have to modify the build files.  How you
    do this, exactly, varies based on platform and what tools you
    have on hand. See <filename>README-Visual-C++.txt</filename>,
    <filename>README-MinGW.txt</filename>, or
    <filename>README-Mac-OS-X.txt</filename>, as appropriate.</para>



  </sect2>













  <sect2 id="max-fields">
    <title>The Maximum Number of Fields Allowed</title>

    <para>MySQL++ offers two ways to automatically build SQL
    queries at run time: <xref linkend="tquery"/> and <link

    linkend="ssqls">SSQLS</link>. There&#x2019;s a limit on the number
    of fields these mechanisms support, defaulting to 25 fields in the
    official MySQL++ packages.<footnote><para>If you&#x2019;re using


    a third-party MySQL++ package, its maintainer may have increased
    these field counts so the resulting headers more closely approach
    the size limit of the compiler the package was built with. In that
    case, you can look at the top of each generated header file to
    find out how many fields each supports.</para></footnote> The files
    embodying these limits are <filename>lib/querydef.h</filename> and
    <filename>lib/ssqls.h</filename>, each generated by Perl scripts of
    the same name but with a <filename>.pl</filename> extension.</para>


    <para>The default <filename>querydef.h</filename> is small and
    its size only increases linearly with respect to maximum field
    count.</para>


    <para><filename>ssqls.h</filename> is a totally
    different story. The default 25 field limit
    makes <filename>ssqls.pl</filename> generate an
    <filename>ssqls.h</filename> over 1&nbsp;MB. Worse,
    the field limit to file size relation is


    <emphasis>quadratic</emphasis>.<footnote><para>The file
    size equation, for you amateur mathematicians out there,
    is <phrase role="math">N<subscript>lines</subscript> =



    18.5f<superscript>2</superscript> + 454.5f + 196.4</phrase>,
    where <varname>f</varname> is the field count.</para></footnote>
    This has a number of bad effects:</para>



    <itemizedlist>
      <listitem>


        <para>Generating header files to support more fields than
        you actually require is a waste of space and bandwidth.</para>
      </listitem>



      <listitem>


        <para>Some compilers have arbitrary limits on the size of
        macros they&#x2019;re able to parse. Exceeding these limits

        usually causes the compiler to misbehave badly, rather than
        fail gracefully.</para>
      </listitem>

      <listitem>


        <para>Because it increases the size of two key files used
        in building MySQL++ itself and programs built on it, it
        increases compile times significantly. One test I did here
        showed a tripling of compile time from quadrupling the field
        limit.</para>
      </listitem>



      <listitem>

        <para>More than 25 fields in a table is a good sign of a bad
        database design, most likely a denormalization problem.</para>
      </listitem>
    </itemizedlist>



    <para>The default limits try to mitigate against all of these
    factors while still being high enough to be useful with most
    DB designs.</para>

    <para>If you&#x2019;re building MySQL++ from source on a platform
    that uses Autoconf, the easiest way to change these limits is at
    configuration time:</para>

    <screen>
./configure --with-field-limit=50</screen>

    <para>That causes the configuration script to pass the
    <command>-f</command> flag to the two Perl scripts named above,
    overriding the default of 25 fields. Obviously you need a
    Perl interpreter on the system for this to work, but Perl is
    usually installed by default on systems MySQL++ supports via
    Autoconf.</para>

    <para>On all other platforms, you&#x2019;ll have to give the
    <command>-f</command> flag to these scripts yourself. This
    may require installing Perl and putting it in the command
    path first. Having done that, you can do something like this to
    raise the limits:</para>

    <screen>
cd lib
perl ssqls.pl -f 50
perl querydef.pl -f 50</screen>

    <para>Note the need to run these commands within the
    <filename>lib</filename> subdirectory of the MySQL++ source


    tree. (This is done for you automatically on systems where you
    are able to use the Autoconf method.)</para>
  </sect2>






  <sect2 id="buried-headers">
    <title>Buried MySQL C API Headers</title>





    <para>It&#x2019;s common these days on Unixy systems to install
    the MySQL C API headers in a <filename>mysql</filename> directory


    under some common <filename>include</filename> directory. If the
    C API headers are in <filename>/usr/include/mysql</filename>, we
    say they are &#x201C;buried&#x201D; underneath the system&#x2019;s
    main include directory, <filename>/usr/include</filename>. Since
    the MySQL++ headers depend on these C API headers, it can be
    useful for MySQL++ to know this fact.</para>



    <para>When MySQL++ includes one of the C API headers, it normally
    does so in the obvious way:</para>

    <programlisting>


#include &lt;mysql.h&gt;
</programlisting>

    <para>But, if you define the
    <varname>MYSQLPP_MYSQL_HEADERS_BURIED</varname> macro, it switches
    to this style:</para>





    <programlisting>
#include &lt;mysql/mysql.h&gt;


</programlisting>

    <para>In common situations like the
    <filename>/usr/include/mysql</filename> one, this simplifies the

    include path options you pass to your compiler.</para>
  </sect2>




  <sect2 id="c99">
    <title>Building MySQL++ on Systems Without Complete C99
    Support</title>


    <para>MySQL++ uses the <ulink
    url="http://en.wikipedia.org/wiki/C_(programming_language)#C99">C99</ulink>
    header <filename>stdint.h</filename> for portable fixed-size
    integer typedefs where possible. The C99 extensions aren&#x2019;t

    yet officially part of the C++ Standard, so there are still
    some C++ compilers that don&#x2019;t offer this header. MySQL++
    works around the lack of this header where it knows it needs
    to, but your platform might not be recognized, causing

    the build to break. If this happens, you can define the
    <varname>MYSQLPP_NO_STDINT_H</varname> macro to make MySQL++
    use its best guess for suitable integer types instead of relying
    on <filename>stdint.h</filename>.</para>


    <para>MySQL++ also uses C99&#x2019;s <type>long long</type>
    data type where available. MySQL++ has workarounds for platforms


    where this is known not to be available, but if you get errors in
    <filename>common.h</filename> about this type, you can define the
    macro <varname>MYSQLPP_NO_LONG_LONGS</varname> to make MySQL++
    fall back to portable constructs.</para>
  </sect2>
</sect1>

Changes to lib/row.h.

1
2
3
4




5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
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
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
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
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
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
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
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
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
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
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
/// \file row.h
/// \brief Declares the classes for holding row data from a result set.

/***********************************************************************




 Copyright (c) 1998 by Kevin Atkinson, (c) 1999-2001 by MySQL AB, and
 (c) 2004-2008 by Educational Technology Resources, Inc.  Others may
 also hold copyrights on code in this file.  See the CREDITS.txt file
 in the top directory of the distribution for details.

 This file is part of MySQL++.

 MySQL++ is free software; you can redistribute it and/or modify it
 under the terms of the GNU Lesser General Public License as published
 by the Free Software Foundation; either version 2.1 of the License, or
 (at your option) any later version.

 MySQL++ is distributed in the hope that it will be useful, but WITHOUT
 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
 License for more details.

 You should have received a copy of the GNU Lesser General Public
 License along with MySQL++; if not, write to the Free Software
 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
 USA
***********************************************************************/

#if !defined(MYSQLPP_ROW_H)
#define MYSQLPP_ROW_H

#include "common.h"

#include "mystring.h"
#include "noexceptions.h"
#include "refcounted.h"
#include "vallist.h"







#include <vector>

#include <string>









namespace mysqlpp {



#if !defined(DOXYGEN_IGNORE)
// Make Doxygen ignore this
class FieldNames;
class MYSQLPP_EXPORT ResultBase;
#endif

/// \brief Manages rows from a result set.
///
/// This class is like an extended version of a \c const \c std::vector
/// of mysqlpp::String.  It adds stuff for populating the vector.  As
/// for why it's \c const, what would it mean to modify a Row?  If we
/// ever did support such semantics, it should probably actually modify
/// the database.  We can't do that if we just derive from std::vector.
///
/// Not that we could derive from std::vector even if we wanted to:
/// \c vector::operator[](size_type) would interfere with our
/// \c operator[](const \c char*).  We can avoid this only by
/// maintaining our own public inteface independent of that of
/// \c vector.

class MYSQLPP_EXPORT Row : public OptionalExceptions
{
private:
	/// \brief Pointer to bool data member, for use by safe bool
	/// conversion operator.
	///
	/// \see http://www.artima.com/cppsource/safebool.html
	typedef bool Row::*private_bool_type;

public:
	/// \brief type of our internal data list
	///
	/// This is public because all other typedefs we have for
	/// mirroring std::vector's public interface depend on it.
	typedef std::vector<String> list_type;

	/// \brief constant iterator type
	typedef list_type::const_iterator const_iterator;

	/// \brief constant reference type
	typedef list_type::const_reference const_reference;

	/// \brief const reverse iterator type
	typedef list_type::const_reverse_iterator const_reverse_iterator;

	/// \brief type for index differences
	typedef list_type::difference_type difference_type;

	/// \brief iterator type
	///
	/// Note that this is just an alias for the const iterator.  Row
	/// is immutable, but people are in the habit of saying 'iterator'
	/// even when they don't intend to use the iterator to modify the
	/// container, so we provide this as a convenience.
	typedef const_iterator iterator;

	/// \brief reference type
	///
	/// \sa iterator for justification for this const_reference alias
	typedef const_reference reference;

	/// \brief mutable reverse iterator type
	///
	/// \sa iterator for justification for this const_reverse_iterator
	/// alias
	typedef const_reverse_iterator reverse_iterator;

	/// \brief type of returned sizes
	typedef list_type::size_type size_type;

	/// \brief type of data in container
	typedef list_type::value_type value_type;

	/// \brief Default constructor
	Row() :
	initialized_(false)
	{
	}
	
	/// \brief Copy constructor
	Row(const Row& r) :
	OptionalExceptions(),
	data_(r.data_.begin(), r.data_.end()),
	field_names_(r.field_names_),
	initialized_(r.initialized_)
	{
	}

	/// \brief Create a row object
	///
	/// \param row MySQL C API row data
	/// \param res result set that the row comes from
	/// \param lengths length of each item in row
	/// \param te if true, throw exceptions on errors
	Row(MYSQL_ROW row, const ResultBase* res,
			const unsigned long* lengths, bool te = true);

	/// \brief Destroy object
	~Row() { }

	/// \brief Get a const reference to the field given its index
	///
	/// \throw mysqlpp::BadIndex if the row is not initialized or there
	/// are less than \c i fields in the row.
	const_reference at(size_type i) const;

	/// \brief Get a reference to the last element of the vector
	const_reference back() const { return data_.back(); }

	/// \brief Return a const iterator pointing to first element in the
	/// container
	const_iterator begin() const { return data_.begin(); }

	/// \brief Returns true if container is empty
	bool empty() const { return data_.empty(); }

	/// \brief Return a const iterator pointing to one past the last
	/// element in the container
	const_iterator end() const { return data_.end(); }

	/// \brief Get an "equal list" of the fields and values in this row
	///
	/// When inserted into a C++ stream, the delimiter 'd' will be used
	/// between the items, " = " is the relationship operator, and items
	/// will be quoted and escaped.
	equal_list_ba<FieldNames, Row, quote_type0>
			equal_list(const char* d = ",", const char* e = " = ") const;

	/// \brief Get an "equal list" of the fields and values in this row
	///
	/// This method's parameters govern how the returned list will
	/// behave when you insert it into a C++ stream:
	///
	/// \param d delimiter to use between items
	/// \param e the operator to use between elements
	/// \param m the manipulator to use for each element
	///
	/// For example, if d is ",", e is " = ", and m is the quote
	/// manipulator, then the field and value lists (a, b) (c, d'e)
	/// will yield an equal list that gives the following when inserted
	/// into a C++ stream:
	///
	/// \code
	///   'a' = 'c', 'b' = 'd''e'
	/// \endcode
	///
	/// Notice how the single quote was 'escaped' in the SQL way to
	/// avoid a syntax error.
	template <class Manip>
	equal_list_ba<FieldNames, Row, Manip> equal_list(const char* d,
			const char* e, Manip m) const;

	/// \brief Get a list of the field names in this row
	///
	/// When inserted into a C++ stream, the delimiter 'd' will be used
	/// between the items, and no manipulator will be used on the items.
	value_list_ba<FieldNames, do_nothing_type0>
			field_list(const char* d = ",") const;

	/// \brief Get a list of the field names in this row
	///
	/// \param d delimiter to place between the items when the list is
	/// inserted into a C++ stream
	/// \param m manipulator to use before each item when the list is
	/// inserted into a C++ stream
	template <class Manip>
	value_list_ba<FieldNames, Manip> field_list(const char* d,
			Manip m) const;

	/// \brief Get a list of the field names in this row
	///
	/// \param d delimiter to place between the items when the list is
	/// inserted into a C++ stream
	/// \param m manipulator to use before each item when the list is
	/// inserted into a C++ stream
	/// \param vb for each true item in this list, add that field name
	/// to the returned list; ignore the others
	template <class Manip>
	value_list_b<FieldNames, Manip> field_list(const char* d, Manip m,
			const std::vector<bool>& vb) const;

	/// \brief Get a list of the field names in this row
	///
	/// \param d delimiter to place between the items when the list is
	/// inserted into a C++ stream
	/// \param vb for each true item in this list, add that field name
	/// to the returned list; ignore the others
	///
	/// Field names will be quoted and escaped when inserted into a C++
	/// stream.
	value_list_b<FieldNames, quote_type0> field_list(
			const char* d, const std::vector<bool>& vb) const;

	/// \brief Get a list of the field names in this row
	///
	/// \param vb for each true item in this list, add that field name
	/// to the returned list; ignore the others
	///
	/// Field names will be quoted and escaped when inserted into a C++
	/// stream, and a comma will be placed between them as a delimiter.
	value_list_b<FieldNames, quote_type0> field_list(
			const std::vector<bool>& vb) const;

	/// \brief Get a list of the field names in this row
	///
	/// For each true parameter, the field name in that position within
	/// the row is added to the returned list.  When the list is
	/// inserted into a C++ stream, the delimiter 'd' will be placed
	/// between the items as a delimiter, and the manipulator 'm' used
	/// before each item.
	template <class Manip>
	value_list_b<FieldNames, Manip> field_list(const char *d, Manip m,
			bool t0,
			bool t1 = false, bool t2 = false, bool t3 = false,
			bool t4 = false, bool t5 = false, bool t6 = false,
			bool t7 = false, bool t8 = false, bool t9 = false,
			bool ta = false, bool tb = false, bool tc = false) const;

	/// \brief Get a list of the field names in this row
	///
	/// For each true parameter, the field name in that position within
	/// the row is added to the returned list.  When the list is
	/// inserted into a C++ stream, the delimiter 'd' will be placed
	/// between the items as a delimiter, and the items will be quoted
	/// and escaped.
	value_list_b<FieldNames, quote_type0> field_list(
			const char *d, bool t0,
			bool t1 = false, bool t2 = false, bool t3 = false,
			bool t4 = false, bool t5 = false, bool t6 = false,
			bool t7 = false, bool t8 = false, bool t9 = false,
			bool ta = false, bool tb = false, bool tc = false) const;

	/// \brief Get a list of the field names in this row
	///
	/// For each true parameter, the field name in that position within
	/// the row is added to the returned list.  When the list is
	/// inserted into a C++ stream, a comma will be placed between the
	/// items as a delimiter, and the items will be quoted and escaped.
	value_list_b<FieldNames, quote_type0> field_list(
			bool t0,
			bool t1 = false, bool t2 = false, bool t3 = false,
			bool t4 = false, bool t5 = false, bool t6 = false,
			bool t7 = false, bool t8 = false, bool t9 = false,
			bool ta = false, bool tb = false, bool tc = false) const;

	/// \brief Returns a field's index given its name
	size_type field_num(const char* name) const;

	/// \brief Get a reference to the first element of the vector
	const_reference front() const { return data_.front(); }

	/// \brief Return maximum number of elements that can be stored
	/// in container without resizing.
	size_type max_size() const { return data_.max_size(); }

	/// \brief Assignment operator
	Row& operator =(const Row& rhs)
	{
		data_.assign(rhs.data_.begin(), rhs.data_.end());
		field_names_.assign(rhs.field_names_);
		initialized_ = rhs.initialized_;
		return *this;
	}

	/// \brief Get the value of a field given its name.
	///
	/// If the field does not exist in this row, we throw a BadFieldName
	/// exception if exceptions are enabled, or an empty row if not.
	/// An empty row tests as false in bool context.
	///
	/// This operator is fairly inefficient.  operator[](int) is faster.
	const_reference operator [](const char* field) const;

	/// \brief Get the value of a field given its index.
	///
	/// This function is just syntactic sugar, wrapping the at() method.
	///
	/// It's \b critical that the parameter type be \c int, not
	/// \c size_type, because it will interfere with the \c const
	/// \c char* overload otherwise.  row[0] is ambiguous when there
	/// isn't an int overload.
	///
	/// \throw mysqlpp::BadIndex if the row is not initialized or there
	/// are less than \c i fields in the row.
	const_reference operator [](int i) const
			{ return at(static_cast<size_type>(i)); }

	/// \brief Returns true if row object was fully initialized and
	/// has data.
	///
	/// This operator lets you use Row in bool context, which lets you
	/// do things like tell when you've run off the end of a "use"
	/// query's result set:
	///
	/// \code
	///   Query q("....");
	///   if (UseQueryResult res = q.use()) {
	///       // Can use 'res', query succeeded
	///       while (Row row = res.fetch_row()) {
	///           // Retreived another row in the result set, can use 'row'
	///       }
	///   }
	/// \endcode
	///
	operator private_bool_type() const
	{
		return data_.size() && initialized_ ? &Row::initialized_ : 0;
	}

	/// \brief Return reverse iterator pointing to first element in the
	/// container
	const_reverse_iterator rbegin() const { return data_.rbegin(); }

	/// \brief Return reverse iterator pointing to one past the last
	/// element in the container
	const_reverse_iterator rend() const { return data_.rend(); }

	/// \brief Get the number of fields in the row.
	size_type size() const { return data_.size(); }

	/// \brief Get a list of the values in this row
	///
	/// When inserted into a C++ stream, the delimiter 'd' will be used
	/// between the items, and the quoting and escaping rules will be
	/// set by the manipulator 'm' you choose.
	///
	/// \param d delimiter to use between values
	/// \param m manipulator to use when inserting values into a stream
	template <class Manip>
	value_list_ba<Row, Manip> value_list(const char* d = ",",
			Manip m = quote) const
	{
		return value_list_ba<Row, Manip>(*this, d, m);
	}
	
	/// \brief Get a list of the values in this row
	///
	/// \param d delimiter to use between values
	/// \param vb for each true item in this list, add that value to the
	/// returned list; ignore the others
	/// \param m manipulator to use when inserting values into a stream
	template <class Manip>
	value_list_b<Row, Manip> value_list(const char *d,
			const std::vector<bool>& vb, Manip m = quote) const
	{
		return value_list_b<Row, Manip>(*this, vb, d, m);
	}
	
	/// \brief Get a list of the values in this row
	///
	/// \param vb for each true item in this list, add that value to the
	/// returned list; ignore the others
	///
	/// Items will be quoted and escaped when inserted into a C++ stream,
	/// and a comma will be used as a delimiter between the items.
	value_list_b<Row, quote_type0> value_list(
			const std::vector<bool> &vb) const
	{
		return value_list_b<Row, quote_type0>(*this, vb, ",", quote);
	}
	
	/// \brief Get a list of the values in this row
	///
	/// For each true parameter, the value in that position within the
	/// row is added to the returned list.  When the list is inserted
	/// into a C++ stream, the delimiter 'd' will be placed between the
	/// items, and the manipulator 'm' used before each item.
	template <class Manip>
	value_list_b<Row, Manip> value_list(const char *d, Manip m,
			bool t0, bool t1 = false, bool t2 = false, bool t3 = false,
			bool t4 = false, bool t5 = false, bool t6 = false,
			bool t7 = false, bool t8 = false, bool t9 = false,
			bool ta = false, bool tb = false, bool tc = false) const
	{
		std::vector<bool> vb;
		create_vector(size(), vb, t0, t1, t2, t3, t4, t5, t6,
				t7, t8, t9, ta, tb, tc);
		return value_list_b<Row, Manip>(*this, vb, d, m);
	}
	
	/// \brief Get a list of the values in this row
	///
	/// For each true parameter, the value in that position within the
	/// row is added to the returned list.  When the list is inserted
	/// into a C++ stream, the delimiter 'd' will be placed between the
	/// items, and items will be quoted and escaped.
	value_list_b <Row, quote_type0>
	value_list(const char *d, bool t0, bool t1 = false, bool t2 = false,
			bool t3 = false, bool t4 = false, bool t5 = false,
			bool t6 = false, bool t7 = false, bool t8 = false,
			bool t9 = false, bool ta = false, bool tb = false,
			bool tc = false) const
	{
		std::vector<bool> vb;
		create_vector(size(), vb, t0, t1, t2, t3, t4, t5, t6,
				t7, t8, t9, ta, tb, tc);
		return value_list_b<Row, quote_type0>(*this, vb, d, quote);
	}
	
	/// \brief Get a list of the values in this row
	///
	/// For each true parameter, the value in that position within the
	/// row is added to the returned list.  When the list is inserted
	/// into a C++ stream, the a comma will be placed between the items,
	/// as a delimiter, and items will be quoted and escaped.
	value_list_b<Row, quote_type0> value_list(bool t0,
			bool t1 = false, bool t2 = false, bool t3 = false,
			bool t4 = false, bool t5 = false, bool t6 = false,
			bool t7 = false, bool t8 = false, bool t9 = false,
			bool ta = false, bool tb = false, bool tc = false) const
	{
		std::vector<bool> vb;
		create_vector(size(), vb, t0, t1, t2, t3, t4, t5, t6,
				t7, t8, t9, ta, tb, tc);
		return value_list_b<Row, quote_type0>(*this, vb, ",", quote);
	}
	
	/// \brief Get a list of the values in this row
	///
	/// The 's' parameters name the fields that will be added to the
	/// returned list.  When inserted into a C++ stream, the delimiter
	/// 'd' will be placed between the items, and the manipulator 'm'
	/// will be inserted before each item.
	template <class Manip>
	value_list_b<Row, Manip> value_list(const char *d, Manip m,
			std::string s0, std::string s1 = "", std::string s2 = "",
			std::string s3 = "", std::string s4 = "",
			std::string s5 = "", std::string s6 = "",
			std::string s7 = "", std::string s8 = "",
			std::string s9 = "", std::string sa = "",
			std::string sb = "", std::string sc = "") const
	{
		std::vector<bool> vb;
		create_vector(*this, vb, s0, s1, s2, s3, s4, s5, s6, s7, s8,
				s9, sa, sb, sc);
		return value_list_b<Row, Manip>(*this, vb, d, m);
	}
	
	/// \brief Get a list of the values in this row
	///
	/// The 's' parameters name the fields that will be added to the
	/// returned list.  When inserted into a C++ stream, the delimiter
	/// 'd' will be placed between the items, and items will be quoted
	/// and escaped.
	value_list_b<Row, quote_type0> value_list(
			const char *d,
			std::string s0, std::string s1 = "", std::string s2 = "",
			std::string s3 = "", std::string s4 = "",
			std::string s5 = "", std::string s6 = "",
			std::string s7 = "", std::string s8 = "",
			std::string s9 = "", std::string sa = "",
			std::string sb = "", std::string sc = "") const
	{
		std::vector<bool> vb;
		create_vector(*this, vb, s0, s1, s2, s3, s4, s5, s6, s7, s8,
				s9, sa, sb, sc);
		return value_list_b<Row, quote_type0>(*this, vb, d, quote);
	}
	
	/// \brief Get a list of the values in this row
	///
	/// The 's' parameters name the fields that will be added to the
	/// returned list.  When inserted into a C++ stream, a comma will be
	/// placed between the items as a delimiter, and items will be
	/// quoted and escaped.
	value_list_b<Row, quote_type0> value_list(
			std::string s0,
			std::string s1 = "", std::string s2 = "",
			std::string s3 = "", std::string s4 = "",
			std::string s5 = "", std::string s6 = "",
			std::string s7 = "", std::string s8 = "",
			std::string s9 = "", std::string sa = "",
			std::string sb = "", std::string sc = "") const
	{
		std::vector<bool> vb;
		create_vector(*this, vb, s0, s1, s2, s3, s4, s5, s6, s7, s8,
				s9, sa, sb, sc);
		return value_list_b<Row, quote_type0>(*this, vb, ",", quote);
	}

private:
	list_type data_;
	RefCountedPointer<FieldNames> field_names_;
	bool initialized_;
};

} // end namespace mysqlpp

#endif // !defined(MYSQLPP_ROW_H)
<
<
<

>
>
>
>
|
|
|
|



















|
|

|

|
|
|
|
>
>
|
>
>
>
>
|
>
|
>
>
>
>
>
>
>
>
|
<
>
>
|
<
|
<
<


<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
|



1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
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
56

57
58
59

60


61
62


































































































































































































































































































































































































































































































63



/***********************************************************************
 threads.h - Abstracts away the differences between POSIX threads and
	Windows native threads.  Used by the cpool example only; we could
	keep this code inline there, but it's really just unimportant
	details.

 Copyright (c) 2008 by Educational Technology Resources, Inc.
 Others may also hold copyrights on code in this file.  See the
 CREDITS.txt file in the top directory of the distribution for details.

 This file is part of MySQL++.

 MySQL++ is free software; you can redistribute it and/or modify it
 under the terms of the GNU Lesser General Public License as published
 by the Free Software Foundation; either version 2.1 of the License, or
 (at your option) any later version.

 MySQL++ is distributed in the hope that it will be useful, but WITHOUT
 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
 License for more details.

 You should have received a copy of the GNU Lesser General Public
 License along with MySQL++; if not, write to the Free Software
 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
 USA
***********************************************************************/

#if !defined(MYSQLPP_THREADS_H)
#define MYSQLPP_THREADS_H

#include <mysql++.h>

#if defined(MYSQLPP_PLATFORM_WINDOWS)
#	define HAVE_THREADS
#	define CALLBACK_SPECIFIER WINAPI
	typedef DWORD thread_return_t;
	typedef LPVOID thread_arg_t;
	static int create_thread(LPTHREAD_START_ROUTINE worker, thread_arg_t arg)
	{
		return CreateThread(0, 0, worker, arg, 0, 0) ? 0 : GetLastError();
	}
	static void sleep(int s) { Sleep(s * 1000); }
#else
#	include "../config.h"
#	if defined(HAVE_UNISTD_H)
#		include <unistd.h>
#	endif
#	if defined(HAVE_PTHREAD)
#		define HAVE_THREADS
#		define CALLBACK_SPECIFIER
		typedef void* thread_return_t;
		typedef void* thread_arg_t;
		static int create_thread(thread_return_t(*worker)(thread_arg_t),
				thread_arg_t arg)
		{

			pthread_t pt;
			return pthread_create(&pt, 0, worker, arg);
		}

#	endif


#endif



































































































































































































































































































































































































































































































#endif // !defined(MYSQLPP_THREADS_H)

Changes to lib/scopedconnection.cpp.

1
2



3
4

5
6
7
8
9
10
11
12
13


























14
15

16


17
18


19

20

21




22


23


24



25
26
27
28










29
30
31

32





33

34



























































35



















































































































































































































































































































































































































































































































































































































































































































































36
37
38

39

40

41

42
43









/***********************************************************************
 scopedconnection.cpp - Implements the ScopedConnection class.




 Copyright (c) 2010 by Switchplane, Ltd.  Others may also hold

 copyrights on code in this file.  See the CREDITS.txt file in the
 top directory of the distribution for details.

 This file is part of MySQL++.

 MySQL++ is free software; you can redistribute it and/or modify it
 under the terms of the GNU Lesser General Public License as published
 by the Free Software Foundation; either version 2.1 of the License, or
 (at your option) any later version.



























 MySQL++ is distributed in the hope that it will be useful, but WITHOUT

 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or


 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
 License for more details.




 You should have received a copy of the GNU Lesser General Public

 License along with MySQL++; if not, write to the Free Software




 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301


 USA


***********************************************************************/




#include "scopedconnection.h"

#include "cpool.h"











namespace mysqlpp {


ScopedConnection::ScopedConnection(ConnectionPool& pool, bool safe) :





pool_(pool),

connection_(safe ? pool.safe_grab() : pool.grab())



























































{



















































































































































































































































































































































































































































































































































































































































































































































}

ScopedConnection::~ScopedConnection()

{

    pool_.release(connection_);

}


} // end namespace mysqlpp









|
|
>
>
>
|
|
>
|
|
|
|
|
|
|
|
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

|
>
|
>
>
|
|
>
>

>
|
>
|
>
>
>
>
|
>
>
|
>
>
|
>
>
>

|

|
>
>
>
>
>
>
>
>
>
>



>
|
>
>
>
>
>
|
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

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


|
>
|
>
|
>
|
>

|
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
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
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
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
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
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
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
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
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
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
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
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
#!/usr/bin/perl -w

########################################################################
# ssqls.pl - Generates ssqls.h, as it defines many near-duplicate
#	functions and classes, varying only in trivial ways.
#
# Copyright (c) 1998 by Kevin Atkinson, (c) 1999-2001 by MySQL AB, and
# (c) 2004-2010 by Educational Technology Resources, Inc.  Others may
# also hold copyrights on code in this file.  See the CREDITS.txt file
# in the top directory of the distribution for details.
#
# This file is part of MySQL++.
#
# MySQL++ is free software; you can redistribute it and/or modify it
# under the terms of the GNU Lesser General Public License as published
# by the Free Software Foundation; either version 2.1 of the License, or
# (at your option) any later version.
#
# MySQL++ is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
# License for more details.
#
# You should have received a copy of the GNU Lesser General Public
# License along with MySQL++; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
# USA
########################################################################


# This is the limit on the number of SSQLS data members.  Higher values
# will make ssqls.h exponentially larger.  This will increase compile
# times and may even expose limits in your compiler.  Increase it only
# if and as far as you must.
my $max_data_members = 25;

# To make comparisons between floating point values, we subtract them,
# take the absolute value, and test to see if that delta is under this
# value.  If it is, we call the two values "equal".  Change this as fits
# your need for precision.  Note that we express it as a string because
# we want the value copied literally into ssqls.h, not "preprocessed" 
# by Perl as a floating-point value.
my $fp_min_delta = "0.00001";


# No user-serviceable parts below.

use strict;
use Getopt::Std;

our $opt_f;
getopts('f:') or die "usage: $0 [-f fields]\n\n";
$max_data_members = int($opt_f) if defined $opt_f;

open (OUT, ">ssqls.h");

print OUT << "---";

// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
// This file is generated by the Perl script ssqls.pl.  Do not modify
// it directly.  Change the script instead.
// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

#if !defined(MYSQLPP_SSQLS_H)
#define MYSQLPP_SSQLS_H

#include "noexceptions.h"
#include "sql_types.h"

#if !defined(MYSQLPP_SSQLS_COMPATIBLE)
#	error Your compiler is not compatible with the SSQLS feature!
#endif

#include <string>

#include <math.h>

// Smallest difference between two floating point numbers recognized
// in making comparisons.  If the absolute delta is under this
// threshold, the two values are considered equal.  You can either
// override this permanently by changing ssqls.pl, or you can do it
// on a case-by-case basis at compile time by defining this to another
// value before #including this header.
#if !defined(MYSQLPP_FP_MIN_DELTA)
#	define MYSQLPP_FP_MIN_DELTA $fp_min_delta
#endif

namespace mysqlpp {

enum sql_dummy_type { sql_dummy };

#ifdef MYSQLPP_SSQLS_NO_STATICS
#	define MYSQLPP_SSQLS_CONDITIONAL_STATICS(...)
#else
#	define MYSQLPP_SSQLS_CONDITIONAL_STATICS(...) __VA_ARGS__
#endif

#define MYSQLPP_SSQLS_MAX_MEMBERS $max_data_members

---

my @types = ("Date", "DateTime", "Time", "String", "std::string");
foreach my $type (@types) {
	print OUT << "---";

inline int sql_cmp(const $type& a, const $type& b)
{
	return a.compare(b);
}
---
}

@types = (
		"signed char", "unsigned char",
		"sql_tinyint", "sql_tinyint_unsigned",
		"signed int", "unsigned",
		"signed short", "unsigned short",
		"signed long", "unsigned long");
foreach my $type (@types) {
	print OUT << "---";

inline int sql_cmp($type a, $type b)
{
	return a - b;
}
---
}

@types = ("longlong", "ulonglong");
foreach my $type (@types) {
	print OUT << "---";

inline int sql_cmp($type a, $type b) 
{
	if (a == b) return 0;
	if (a <  b) return -1;
	return 1;
}
---
}	

@types = ("double", "float");
foreach my $type (@types) {
	print OUT << "---";

inline int sql_cmp($type a, $type b) 
{
	if (fabs(a - b) < MYSQLPP_FP_MIN_DELTA) return 0;
	if (a <  b) return -1;
	return 1;
}
---
}	

print OUT << "---";

template <typename T>
inline int sql_cmp(const mysqlpp::Null<T>& a, const mysqlpp::Null<T>& b) 
{
	if (a == b) return 0;
	if (a <  b) return -1;
	return 1;
}


// ---------------------------------------------------
//                Begin Mandatory Compare 
// ---------------------------------------------------

#define sql_compare_define(NAME) \\
	bool operator == (const NAME &other) const \\
		{return sql_compare_##NAME<mysqlpp::sql_dummy>(*this,other) == 0;} \\
	bool operator != (const NAME &other) const \\
		{return sql_compare_##NAME<mysqlpp::sql_dummy>(*this,other) != 0;} \\
	bool operator > (const NAME &other) const \\
		{return sql_compare_##NAME<mysqlpp::sql_dummy>(*this,other) >  0;} \\
	bool operator < (const NAME &other) const \\
		{return sql_compare_##NAME<mysqlpp::sql_dummy>(*this,other) <  0;} \\
	bool operator >= (const NAME &other) const \\
		{return sql_compare_##NAME<mysqlpp::sql_dummy>(*this,other) >= 0;} \\
	bool operator <= (const NAME &other) const \\
		{return sql_compare_##NAME<mysqlpp::sql_dummy>(*this,other) <= 0;} \\
	int cmp (const NAME &other) const \\
		{return sql_compare_##NAME<mysqlpp::sql_dummy>(*this,other);} \\
	int compare (const NAME &other) const \\
		{return sql_compare_##NAME<mysqlpp::sql_dummy>(*this,other);}
---

my ($parm0, $parm1);

foreach my $j (1..$max_data_members) {
	$parm0 .= "T$j, C$j";
	$parm0 .= ", " unless $j == $max_data_members;
	$parm1 .= "C$j";
	$parm1 .= ", " unless $j == $max_data_members;
}

print OUT << "---";

#define sql_compare_define_0(NAME, $parm0)

#define sql_construct_define_0(NAME, $parm0)

#define sql_COMPARE__0(NAME, $parm1)

#define sql_compare_type_def_0(NAME, WHAT, NUM) \\
	sql_compare_type_def_##NUM(NAME, WHAT, NUM)

#define sql_compare_type_defe_0(NAME, WHAT, NUM) \\
	sql_compare_type_defe_##NUM(NAME, WHAT, NUM)

// ---------------------------------------------------
//                 End Mandatory Compare 
// ---------------------------------------------------
---


foreach my $i (1..$max_data_members) {
	my ($compr, $define, $compp, $set, $parm2);

	$compr = ""; $parm2 = ""; $define = "";
	$compr = "    int cmp; \\\n" unless $i == 1;
	$compp = "";
	$set = "";

	foreach my $j (1..$i) {
		if ($j != $i) {
			$compr .= "    cmp = mysqlpp::sql_cmp(x.C$j , y.C$j ); \\\n";
			$compr .= "    if (cmp) return cmp; \\\n";
		}

		$compr .= "    return mysqlpp::sql_cmp(x.C$j , y.C$j );" if $j == $i;
		$parm2 .= "const T$j &p$j";
		$parm2 .= ", " unless $j == $i;
		$define.= "C$j (p$j)";
		$define.= ", " unless $j == $i;
		$set   .= "    C$j = p$j;\\\n";
		$compp .= "true";
		$compp .= ", " unless $j == $i;
	}
	print OUT << "---";

// ---------------------------------------------------
//                   Begin Compare $i
// ---------------------------------------------------

#define sql_compare_define_$i(NAME, $parm0) \\
	NAME($parm2) : $define, table_override_(0) {} \\
	void set($parm2) { \\
	table_override_ = 0; \\
$set \\
	} \\
	sql_compare_define(NAME)

#define sql_construct_define_$i(NAME, $parm0) \\
	void set($parm2) { \\
	table_override_ = 0; \\
$set \\
	} \\
	NAME($parm2) : $define, table_override_(0) {}

#define sql_compare_type_def_$i(NAME, WHAT, NUM) \\
	return WHAT##_list(d, m, $compp)

#define sql_compare_type_defe_$i(NAME, WHAT, NUM) \\
	return WHAT##_list(d, c, m, $compp)

#define sql_COMPARE__$i(NAME, $parm1) \\
	template <mysqlpp::sql_dummy_type dummy> \\
	int sql_compare_##NAME(const NAME &x, const NAME &y) { \\
$compr \\
	} \\
	template <mysqlpp::sql_dummy_type dummy> \\
	int compare (const NAME &x, const NAME &y) { \\
$compr \\
	}

// ---------------------------------------------------
//                   End Compare $i
// ---------------------------------------------------

---
}


foreach my $i (1..$max_data_members) {
	my $create_bool = "";
	my $create_list = "";
	my $cus_equal_list = "";
	my $cus_field_list = "";
	my $cusparms1 = "";
	my $cusparms11 = "";
	my $cusparms2 = "";
	my $cusparms22 = "";
	my $cusparmsv = "";
	my $defs = "";
	my $enums = "";
	my $equal_list = "";
	my $field_list = "";
	my $names = "";
	my $parmc = "";
	my $parmC = "";
	my $parm_complete = "";
	my $parm_simple = "";
	my $parm_simple2c = "";
	my $parm_simple2c_b = "";
	my $parm_simple_b = "";
	my $popul = "";
	my $value_list = "";
	my $value_list_cus = "";

	foreach my $j (1 .. $i) {
		$parm_complete .= "T$j, I$j, N$j";
		$parm_complete .= ", " unless $j == $i;
		$parm_simple   .= "T$j, I$j";
		$parm_simple   .= ", " unless $j == $i;
		$parm_simple2c .= "T$j, I$j, #I$j";
		$parm_simple2c .= ", " unless $j == $i;
		$parm_simple_b   .= "T$j, I$j";
		$parm_simple_b   .= ", " unless $j == $i;
		$parm_simple2c_b .= "T$j, I$j";
		$parm_simple2c_b .= ", " unless $j == $i;

		$defs  .= "    T$j I$j;";
		$defs  .= "\n" unless $j == $i;

		$popul .= "    s->I$j = row[N$j].conv(T$j());";
		$popul .= "\n" unless $j == $i;

		$names .= "    N$j ";
		$names .= ",\n" unless $j == $i;
		$enums .= "    NAME##_##I$j";
		$enums .= ",\n" unless $j == $i;

		$field_list .= "    s << obj.manip << '`' << obj.obj->names[".($j-1)."] << '`'";
		$field_list .= " << obj.delim;\n" unless $j == $i;

		$value_list .= "    s << obj.manip << obj.obj->I$j";
		$value_list .= " << obj.delim;\n" unless $j == $i;

		$create_bool .= "    if (i$j) (*include)[".($j-1)."]=true;\n";

		$create_list .= "    if (i$j == NAME##_NULL) return;\n" unless $i == 1;
		$create_list .= "    (*include)[i$j]=true;\n";

		$value_list_cus .= "    if ((*obj.include)[".($j-1)."]) { \n";
		$value_list_cus .= "      if (before) s << obj.delim;\n" unless $j == 1;
		$value_list_cus .= "      s << obj.manip << obj.obj->I$j;\n";
		$value_list_cus .= "      before = true; \n" unless $j == $i;
		$value_list_cus .= "     } \n";

		$cus_field_list .= "    if ((*obj.include)[".($j-1)."]) { \n";
		$cus_field_list .= "      if (before) s << obj.delim;\n" unless $j == 1;
		$cus_field_list .= "      s << obj.manip << '`' << obj.obj->names[".($j-1)."] << '`';\n";
		$cus_field_list .= "      before = true; \n" unless $j == $i;
		$cus_field_list .= "     } \n";

		$cus_equal_list .= "    if ((*obj.include)[".($j-1)."]) { \n";
		$cus_equal_list .= "      if (before) s << obj.delim;\n" unless $j == 1;
		$cus_equal_list .= "      s << '`' << obj.obj->names[".($j-1)."] << '`' << obj.comp";
		$cus_equal_list .=        " << obj.manip << obj.obj->I$j;\n";
		$cus_equal_list .= "      before = true; \n" unless $j == $i;
		$cus_equal_list .= "     } \n";

		$equal_list .= "    s << '`' << obj.obj->names[".($j-1)."] << '`' << obj.comp";
		$equal_list .= " << obj.manip << obj.obj->I$j";
		$equal_list .= " << obj.delim;\n" unless $j == $i;

		$cusparms1  .= "bool i$j"         if     $j == 1;
		$cusparms1  .= "bool i$j = false" unless $j == 1;
		$cusparms1  .= ", " unless $j == $i;
		$cusparms11  .= "bool i$j" ;
		$cusparms11  .= ", " unless $j == $i;
		$cusparms2  .= "NAME##_enum i$j" if $j == 1;
		$cusparms2  .= "NAME##_enum i$j = NAME##_NULL" unless $j == 1;
		$cusparms2  .= ", " unless $j == $i;
		$cusparms22  .= "NAME##_enum i$j";
		$cusparms22  .= ", " unless $j == $i;
		$cusparmsv  .= "i$j";
		$cusparmsv  .= ", " unless $j == $i;

		$parmC .= "T$j, I$j";
		$parmC .= ", " unless $j == $max_data_members;
		$parmc .= "I$j";
		$parmc .= ", " unless $j == $max_data_members;
	}

	foreach my $j ($i + 1 .. $max_data_members) {
		$parmC .= "0, 0";
		$parmC .= ", " unless $j == $max_data_members;
		$parmc .= "0";
		$parmc .= ", " unless $j == $max_data_members;
	}

	print OUT << "---";
// ---------------------------------------------------
//                  Begin Create $i
// ---------------------------------------------------
---
	my $out = <<"---";
#define sql_create_complete_$i(NAME, CMP, CONTR, $parm_complete) 
	struct NAME; 

	enum NAME##_enum { 
$enums 
	,NAME##_NULL 
	}; 

	template <class Manip>
	class NAME##_value_list { 
	public: 
	const NAME* obj;
	const char* delim;
	Manip manip;
	public: 
	NAME##_value_list (const NAME* o, const char* d, Manip m) :
	obj(o), delim(d), manip(m) { } 
	};

	template <class Manip>
	class NAME##_##field_list {
	public: 
	const NAME* obj; 
	const char* delim;
	Manip manip;
	public: 
	NAME##_field_list (const NAME* o, const char* d, Manip m) :
	obj(o), delim(d), manip(m) { } 
	};

	template <class Manip>
	class NAME##_equal_list { 
	public: 
	const NAME* obj;
	const char* delim;
	const char* comp;
	Manip manip;
	public: 
	NAME##_equal_list (const NAME* o, const char* d, const char* c, Manip m) :
	obj(o), delim(d), comp(c), manip(m) { }
	};

	template <class Manip>
	class NAME##_cus_value_list {
	public:
	const NAME* obj;
	std::vector<bool> *include;
	bool del_vector;
	const char* delim;
	Manip manip;
	public: 
	~NAME##_cus_value_list () {if (del_vector) delete include;} 
	NAME##_cus_value_list (const NAME* o, const char* d, Manip m, $cusparms11);
	NAME##_cus_value_list (const NAME* o, const char* d, Manip m, $cusparms22); 
	NAME##_cus_value_list (const NAME* o, const char* d, Manip m ,std::vector<bool>* i) :
	obj(o), include(i), del_vector(false), delim(d), manip(m) { }
	};

	template <class Manip>
	class NAME##_cus_field_list { 
	public:
	const NAME* obj; 
	std::vector<bool> *include; 
	bool del_vector; 
	const char* delim;
	Manip manip;
	public: 
	~NAME##_cus_field_list () {if (del_vector) delete include;} 
	NAME##_cus_field_list (const NAME* o, const char* d, Manip m, $cusparms11); 
	NAME##_cus_field_list (const NAME* o, const char* d, Manip m, $cusparms22); 
	NAME##_cus_field_list (const NAME* o, const char* d, Manip m, std::vector<bool> *i) :
	obj(o), include(i), del_vector(false), delim(d), manip(m) { }
	};

	template <class Manip>
	class NAME##_cus_equal_list {
	public:
	const NAME* obj;
	std::vector<bool> *include;
	bool del_vector;
	const char* delim;
	const char* comp;
	Manip manip;
	public:
	~NAME##_##cus_equal_list () {if (del_vector) delete include;}
	NAME##_##cus_equal_list (const NAME* o, const char* d, const char* c, Manip m, $cusparms11); 
	NAME##_##cus_equal_list (const NAME* o, const char* d, const char* c, Manip m, $cusparms22); 
	NAME##_##cus_equal_list (const NAME* o, const char* d, const char* c, Manip m, std::vector<bool> *i) :
	obj(o), include(i), del_vector(false), delim(d), comp(c), manip(m) { }
	};

	template <mysqlpp::sql_dummy_type dummy> int sql_compare_##NAME(const NAME&, const NAME&);

	struct NAME {
$defs 
	NAME() : table_override_(0) { }
	NAME(const mysqlpp::Row& row);
	void set(const mysqlpp::Row &row);
	sql_compare_define_##CMP(NAME, $parmC)
	sql_construct_define_##CONTR(NAME, $parmC)
	static const char* names[];
	static void table(const char* t) { table_ = t; }
	const char* table() const
			{ return table_override_ ? table_override_ : NAME::table_; }
	void instance_table(const char* t) { table_override_ = t; }

	NAME##_value_list<mysqlpp::quote_type0> value_list() const {
		return value_list(",", mysqlpp::quote);}
	NAME##_value_list<mysqlpp::quote_type0> value_list(const char* d) const {
		return value_list(d, mysqlpp::quote);}
	template <class Manip>
	NAME##_value_list<Manip> value_list(const char* d, Manip m) const;

	NAME##_field_list<mysqlpp::do_nothing_type0> field_list() const {
		return field_list(",", mysqlpp::do_nothing);}
	NAME##_field_list<mysqlpp::do_nothing_type0> field_list(const char* d) const {
		return field_list(d, mysqlpp::do_nothing);}
	template <class Manip>
	NAME##_field_list<Manip> field_list(const char* d, Manip m) const;

	NAME##_equal_list<mysqlpp::quote_type0> equal_list(const char* d = ",",
			const char* c = " = ") const
			{ return equal_list(d, c, mysqlpp::quote); }
	template <class Manip>
	NAME##_equal_list<Manip> equal_list(const char* d, const char* c, Manip m) const;

	/* cus_data */

	NAME##_cus_value_list<mysqlpp::quote_type0> value_list($cusparms1) const
			{ return value_list(",", mysqlpp::quote, $cusparmsv); }
	NAME##_cus_value_list<mysqlpp::quote_type0> value_list($cusparms2) const
			{ return value_list(",", mysqlpp::quote, $cusparmsv); }
	NAME##_cus_value_list<mysqlpp::quote_type0> value_list(std::vector<bool> *i) const
			{ return value_list(",", mysqlpp::quote, i); }
	NAME##_cus_value_list<mysqlpp::quote_type0> value_list(mysqlpp::sql_cmp_type sc) const
			{ return value_list(",", mysqlpp::quote, sc); }

	NAME##_cus_value_list<mysqlpp::quote_type0> value_list(const char* d, $cusparms1) const
			{ return value_list(d, mysqlpp::quote, $cusparmsv); }
	NAME##_cus_value_list<mysqlpp::quote_type0> value_list(const char* d, $cusparms2) const
			{ return value_list(d, mysqlpp::quote, $cusparmsv); }
	NAME##_cus_value_list<mysqlpp::quote_type0> value_list(const char* d,
			std::vector<bool> *i) const
			{ return value_list(d, mysqlpp::quote, i); }
	NAME##_cus_value_list<mysqlpp::quote_type0> value_list(const char* d,
			mysqlpp::sql_cmp_type sc) const
			{ return value_list(d, mysqlpp::quote, sc); }

	template <class Manip>
	NAME##_cus_value_list<Manip> value_list(const char* d, Manip m,
			$cusparms1) const;
	template <class Manip>
	NAME##_cus_value_list<Manip> value_list(const char* d, Manip m,
			$cusparms2) const;
	template <class Manip>
	NAME##_cus_value_list<Manip> value_list(const char* d, Manip m,
			std::vector<bool>* i) const;
	template <class Manip>
	NAME##_cus_value_list<Manip> value_list(const char* d, Manip m, 
			mysqlpp::sql_cmp_type sc) const;
	/* cus field */

	NAME##_cus_field_list<mysqlpp::do_nothing_type0> field_list($cusparms1) const 
			{ return field_list(",", mysqlpp::do_nothing, $cusparmsv); }
	NAME##_cus_field_list<mysqlpp::do_nothing_type0> field_list($cusparms2) const
			{ return field_list(",", mysqlpp::do_nothing, $cusparmsv); }
	NAME##_cus_field_list<mysqlpp::do_nothing_type0> field_list(std::vector<bool> *i) const
			{ return field_list(",", mysqlpp::do_nothing, i); }
	NAME##_cus_field_list<mysqlpp::do_nothing_type0> field_list(mysqlpp::sql_cmp_type sc) const
			{ return field_list(",", mysqlpp::do_nothing, sc); }

	NAME##_cus_field_list<mysqlpp::do_nothing_type0> field_list(const char* d,
			$cusparms1) const
			{ return field_list(d, mysqlpp::do_nothing, $cusparmsv); }
	NAME##_cus_field_list<mysqlpp::do_nothing_type0> field_list(const char* d,
			$cusparms2) const
			{ return field_list(d, mysqlpp::do_nothing, $cusparmsv); }
	NAME##_cus_field_list<mysqlpp::do_nothing_type0> field_list(const char* d,
			std::vector<bool>* i) const
			{ return field_list(d, mysqlpp::do_nothing, i); }
	NAME##_cus_field_list<mysqlpp::do_nothing_type0> field_list(const char* d,
			mysqlpp::sql_cmp_type sc) const
			{ return field_list(d, mysqlpp::do_nothing, sc); }

	template <class Manip>
	NAME##_cus_field_list<Manip> field_list(const char* d, Manip m,
			$cusparms1) const;
	template <class Manip>
	NAME##_cus_field_list<Manip> field_list(const char* d, Manip m,
			$cusparms2) const;
	template <class Manip>
	NAME##_cus_field_list<Manip> field_list(const char* d, Manip m,
			std::vector<bool> *i) const;
	template <class Manip>
	NAME##_cus_field_list<Manip> field_list(const char* d, Manip m,
			mysqlpp::sql_cmp_type sc) const;

	/* cus equal */

	NAME##_cus_equal_list<mysqlpp::quote_type0> equal_list($cusparms1) const
			{ return equal_list(",", " = ", mysqlpp::quote, $cusparmsv); }
	NAME##_cus_equal_list<mysqlpp::quote_type0> equal_list($cusparms2) const
			{ return equal_list(",", " = ", mysqlpp::quote, $cusparmsv); }
	NAME##_cus_equal_list<mysqlpp::quote_type0> equal_list(std::vector<bool>* i) const
			{ return equal_list(",", " = ", mysqlpp::quote, i); }
	NAME##_cus_equal_list<mysqlpp::quote_type0> equal_list(mysqlpp::sql_cmp_type sc) const
			{ return equal_list(",", " = ", mysqlpp::quote, sc); }

	NAME##_cus_equal_list<mysqlpp::quote_type0> equal_list(const char* d, $cusparms1) const
			{ return equal_list(d, " = ", mysqlpp::quote, $cusparmsv); }
	NAME##_cus_equal_list<mysqlpp::quote_type0> equal_list(const char* d, $cusparms2) const
			{ return equal_list(d, " = ", mysqlpp::quote, $cusparmsv); }
	NAME##_cus_equal_list<mysqlpp::quote_type0> equal_list(const char* d,
			std::vector<bool> *i) const
			{ return equal_list(d, " = ", mysqlpp::quote, i); }
	NAME##_cus_equal_list<mysqlpp::quote_type0> equal_list(const char* d,
			mysqlpp::sql_cmp_type sc) const
			{ return equal_list(d, " = ", mysqlpp::quote, sc); }

	NAME##_cus_equal_list<mysqlpp::quote_type0> equal_list(const char* d, const char* c,
			$cusparms1) const
			{ return equal_list(d, c, mysqlpp::quote, $cusparmsv); }
	NAME##_cus_equal_list<mysqlpp::quote_type0> equal_list(const char* d, const char* c,
			$cusparms2) const
			{ return equal_list(d, c, mysqlpp::quote, $cusparmsv); }
	NAME##_cus_equal_list<mysqlpp::quote_type0> equal_list(const char* d, const char* c,
			std::vector<bool> *i) const
			{ return equal_list(d, c, mysqlpp::quote, i); }
	NAME##_cus_equal_list<mysqlpp::quote_type0> equal_list(const char* d, const char* c,
			mysqlpp::sql_cmp_type sc) const
			{ return equal_list(d, c, mysqlpp::quote, sc); }

	template <class Manip>
	NAME##_cus_equal_list<Manip> equal_list(const char* d, const char* c, Manip m, 
						$cusparms1) const;
	template <class Manip>
	NAME##_cus_equal_list<Manip> equal_list(const char* d, const char* c, Manip m, 
						$cusparms2) const;
	template <class Manip>
	NAME##_cus_equal_list<Manip> equal_list(const char* d, const char* c, Manip m, 
						std::vector<bool> *i) const;
	template <class Manip>
	NAME##_cus_equal_list<Manip> equal_list(const char* d, const char* c, Manip m, 
						mysqlpp::sql_cmp_type sc) const;

	private:
	static const char* table_;
	const char* table_override_;
	};
	MYSQLPP_SSQLS_CONDITIONAL_STATICS(
		const char* NAME::names[] = {
			$names
		};
		const char* NAME::table_ = #NAME;
	)

	template <class Manip>
	NAME##_cus_value_list<Manip>::NAME##_cus_value_list
			(const NAME* o, const char* d, Manip m, $cusparms11)
	{
		delim = d;
		manip = m;
		del_vector = true;
		obj = o;
		include = new std::vector<bool>($i, false);
$create_bool
	}

	template <class Manip>
	NAME##_cus_value_list<Manip>::NAME##_cus_value_list
			(const NAME* o, const char* d, Manip m, $cusparms22)
	{
		delim = d;
		manip = m;
		del_vector = true;
		obj = o;
		include = new std::vector<bool>($i, false);
$create_list
	}

	template <class Manip>
	NAME##_cus_field_list<Manip>::NAME##_cus_field_list
			(const NAME* o, const char* d, Manip m, $cusparms11)
	{
		delim = d;
		manip = m;
		del_vector = true;
		obj = o;
		include = new std::vector<bool>($i, false);
$create_bool
	}

	template <class Manip>
	NAME##_cus_field_list<Manip>::NAME##_cus_field_list
			(const NAME* o, const char* d, Manip m, $cusparms22)
	{
		delim = d;
		manip = m;
		del_vector = true;
		obj = o;
		include = new std::vector<bool>($i, false);
$create_list
	}

	template <class Manip>
	NAME##_cus_equal_list<Manip>::NAME##_cus_equal_list
			(const NAME* o, const char* d, const char* c, Manip m, $cusparms11)
	{
		delim = d;
		comp = c;
		manip = m;
		del_vector = true;
		obj = o;
		include = new std::vector<bool>($i, false);
$create_bool
	}

	template <class Manip>
	NAME##_cus_equal_list<Manip>::NAME##_cus_equal_list
			(const NAME* o, const char* d, const char* c, Manip m, $cusparms22)
	{
		delim = d;
		comp = c;
		manip = m;
		del_vector = true;
		obj = o;
		include = new std::vector<bool>($i, false);
$create_list
	}

	template <class Manip>
	std::ostream& operator <<(std::ostream& s, const NAME##_value_list<Manip>& obj)
	{
$value_list;
		return s;
	}

	template <class Manip>
	std::ostream& operator <<(std::ostream& s, const NAME##_field_list<Manip>& obj)
	{
$field_list;
		return s;
	}

	template <class Manip>
	std::ostream& operator <<(std::ostream& s, const NAME##_equal_list<Manip>& obj)
	{
$equal_list;
		return s;
	}

	template <class Manip>
	std::ostream& operator <<(std::ostream& s, const NAME##_cus_value_list<Manip>& obj)
	{
		bool before = false;
$value_list_cus
		return s;
	}

	template <class Manip>
	std::ostream& operator <<(std::ostream& s, const NAME##_cus_field_list<Manip>& obj)
	{
		bool before = false;
$cus_field_list
		return s;
	}

	template <class Manip>
	std::ostream& operator <<(std::ostream& s, const NAME##_cus_equal_list<Manip>& obj)
	{
		bool before = false;
$cus_equal_list
		return s;
	}

	template <class Manip>
	inline NAME##_value_list<Manip> NAME::value_list(const char* d, Manip m) const
			{ return NAME##_value_list<Manip> (this, d, m); } 

	template <class Manip>
	inline NAME##_field_list<Manip> NAME::field_list(const char* d, Manip m) const
			{ return NAME##_field_list<Manip> (this, d, m); } 

	template <class Manip>
	inline NAME##_equal_list<Manip> NAME::equal_list(const char* d, const char* c, Manip m) const
			{ return NAME##_equal_list<Manip> (this, d, c, m); } 

	template <class Manip>
	inline NAME##_cus_value_list<Manip> NAME::value_list(const char* d, Manip m,
			$cusparms11) const
			{ return NAME##_cus_value_list<Manip> (this, d, m, $cusparmsv); }

	template <class Manip>
	inline NAME##_cus_field_list<Manip> NAME::field_list(const char* d, Manip m,
			$cusparms11) const
			{ return NAME##_cus_field_list<Manip> (this, d, m, $cusparmsv); }

	template <class Manip>
	inline NAME##_cus_equal_list<Manip> NAME::equal_list(const char* d, const char* c, Manip m,
			$cusparms11) const
			{ return NAME##_cus_equal_list<Manip> (this, d, c, m, $cusparmsv); } 

	template <class Manip>
	inline NAME##_cus_value_list<Manip> NAME::value_list(const char* d, Manip m,
			$cusparms22) const
			{ return NAME##_cus_value_list<Manip> (this, d, m, $cusparmsv); } 

	template <class Manip>
	inline NAME##_cus_field_list<Manip> NAME::field_list(const char* d, Manip m,
			$cusparms22) const
			{ return NAME##_cus_field_list<Manip> (this, d, m, $cusparmsv); } 

	template <class Manip>
	inline NAME##_cus_equal_list<Manip> NAME::equal_list(const char* d, const char* c, Manip m, 
			$cusparms22) const
			{ return NAME##_cus_equal_list<Manip> (this, d, c, m, $cusparmsv); } 

	template <class Manip>
	inline NAME##_cus_value_list<Manip> NAME::value_list(const char* d, Manip m,
			std::vector<bool> *i) const
			{ return NAME##_cus_value_list<Manip> (this, d, m, i); }

	template <class Manip>
	inline NAME##_cus_field_list<Manip> NAME::field_list(const char* d, Manip m,
			std::vector<bool> *i) const
			{ return NAME##_cus_field_list<Manip> (this, d, m, i); }

	template <class Manip>
	inline NAME##_cus_equal_list<Manip> NAME::equal_list(const char* d, const char* c, Manip m,
			std::vector<bool> *i) const
			{ return NAME##_cus_equal_list<Manip> (this, d, c, m, i); }

	template <class Manip>
	inline NAME##_cus_value_list<Manip> 
	NAME::value_list(const char* d, Manip m, mysqlpp::sql_cmp_type /*sc*/) const
			{ sql_compare_type_def_##CMP(NAME, value, NUM); }

	template <class Manip>
	inline NAME##_cus_field_list<Manip> 
	NAME::field_list(const char* d, Manip m, mysqlpp::sql_cmp_type /*sc*/) const
			{ sql_compare_type_def_##CMP(NAME, field, NUM); }

	template <class Manip>
	inline NAME##_cus_equal_list<Manip> 
	NAME::equal_list(const char* d, const char* c, Manip m, mysqlpp::sql_cmp_type /*sc*/) const
			{ sql_compare_type_defe_##CMP(NAME, equal, NUM); }

	template <mysqlpp::sql_dummy_type dummy>
	void populate_##NAME(NAME *s, const mysqlpp::Row &row)
	{
		mysqlpp::NoExceptions ignore_schema_mismatches(row);
$popul
	}

	inline NAME::NAME(const mysqlpp::Row& row) :
	table_override_(0)
			{ populate_##NAME<mysqlpp::sql_dummy>(this, row); }
	inline void NAME::set(const mysqlpp::Row& row)
	{
		table_override_ = 0;
		populate_##NAME<mysqlpp::sql_dummy>(this, row);
	}

	sql_COMPARE__##CMP(NAME, $parmc )

---
print OUT &prepare($out);

#
# short cut defs
#

print OUT << "---";
#define sql_create_$i(NAME, CMP, CONTR, $parm_simple) \\
		sql_create_complete_$i(NAME, CMP, CONTR, $parm_simple2c) \\

// ---------------------------------------------------
//                  End Create $i
// ---------------------------------------------------

---

}


print OUT << "---";

} // end namespace mysqlpp

#endif // !defined(MYSQLPP_SSQLS_H)

---


sub prepare {
	local $_ = $_[0];
	s/\n+$//;
	s/\n[\n ]*\n/\n/g; 
	s/\n+/\\\n/g;
	$_ .= "\n\n";
	return $_;
}

Changes to lib/scopedconnection.h.

1



2



3
4


5
6


7
8

9

10

11
12


13
14
15




16

17
18

19



20
21
22
23
24
25

26
27
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






56

57
58

59
60

61
62
63
64
65

66
67
68
69
70
71





72
73
74


75
76
77
78
79
80
81
82

83


84
85


86

87
88

89







90



/// \file scopedconnection.h



/// \brief Declares the ScopedConnection class.



///
/// This class lets you grab a connection from a ConnectionPool in a


/// scoped and therefore RAII way.  The Connection object will always be
/// returned to the pool when the scope block ends, plugging a potential


/// leak in the pool.


/***********************************************************************

 Copyright (c) 2010 by Joel Fielder.  Others may also hold copyrights

 on code in this file.  See the CREDITS.txt file in the top directory
 of the distribution for details.



 This file is part of MySQL++.





 MySQL++ is free software; you can redistribute it and/or modify it

 under the terms of the GNU Lesser General Public License as published
 by the Free Software Foundation; either version 2.1 of the License, or

 (at your option) any later version.




 MySQL++ is distributed in the hope that it will be useful, but WITHOUT
 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
 License for more details.


 You should have received a copy of the GNU Lesser General Public
 License along with MySQL++; if not, write to the Free Software
 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
 USA
***********************************************************************/

#if !defined(MYSQLPP_SCOPEDCONNECTION_H)
#define MYSQLPP_SCOPEDCONNECTION_H




#include "common.h"


namespace mysqlpp {









#if !defined(DOXYGEN_IGNORE)


// Make Doxygen ignore this



class MYSQLPP_EXPORT Connection;
class MYSQLPP_EXPORT ConnectionPool;
#endif










/// \brief Grabs a Connection from a ConnectionPool on construction


/// and releases it back to the pool on destruction, and provides access

/// to the relevant Connection pointer.
class MYSQLPP_EXPORT ScopedConnection

{
public:

	/// \brief Standard constructor








	///
	/// Grabs a Connection from the specified pool.
	///
	/// \internal Note that there is no default ctor on purpose.  RAII.






	///

	/// \param pool The ConnectionPool to use.
	/// \param safe By default, we get the connection from the pool with

	/// ConnectionPool::grab(), but we can call safe_grab() instead.
	explicit ScopedConnection(ConnectionPool& pool, bool safe = false);


	/// \brief Destructor
	///
	/// Releases the Connection back to the ConnectionPool.
	~ScopedConnection();


	/// \brief Access the Connection pointer
	Connection* operator->() const { return connection_; }

	/// \brief Dereference
	Connection& operator*() const { return *connection_; }






	/// \brief Truthiness operator
	operator void*() const { return connection_; }



private:
	// ScopedConnection objects cannot be copied.  We want them to be
	// tightly scoped to their use point, not put in containers or
	// passed around promiscuously.
	ScopedConnection(const ScopedConnection& no_copies);   
	const ScopedConnection& operator=(const ScopedConnection& no_copies);


	ConnectionPool& pool_;


	Connection* const connection_;
};




} // end namespace mysqlpp


#endif // !defined(MYSQLPP_SCOPEDCONNECTION_H)











|
>
>
>
|
>
>
>
|
|
>
>
|
<
>
>
|

>
|
>
|
>
|
|
>
>

|

>
>
>
>
|
>
|
|
>
|
>
>
>

|
<
|
<
|
>
|
<
<
<
<
|
|
|

>
>
>
|

>
|
>
>
>

>
>
>
>
>
|
>
>
|
>
>
>
|
|
|
>
>
>
>
>
>
>
>
>

<
>
>
|
>
|
<
>
|
|
>
|
>
>
>
>
>
>
>
>
|
|
<
|
>
>
>
>
>
>
|
>
|
|
>
|
<
>

<
<
<
<
>

<
|

|
|
>
>
>
>
>

<
<
>
>

<
<
<
<
<
|
|
>
|
>
>
|
|
>
>

>
|

>
|
>
>
>
>
>
>
>

>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13

14
15
16
17
18
19
20
21
22
23
24
25
26
27
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
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88

89
90
91
92
93

94
95
96
97
98
99
100
101
102
103
104
105
106
107
108

109
110
111
112
113
114
115
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
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
Prerequisite: GCC Version
~~~~~~~~~~~~~~~~~~~~~~~~~
    If your MinGW version isn't using at least GCC 3.4.5, it needs
    to be updated.  Older versions are known to not work with MySQL++.

    As of MySQL++ 3.1.1, the required version might need to be even
    newer, as we are now depending on improvements to the MinGW linker
    which probably don't go back that far.


Prerequisite: MySQL C Development Files
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    MySQL++ is built atop MySQL's C API library.  The easiest way to

    get that is to install Connector/C on your development system,
    which you can download from mysql.com.  The distribution assumes
    these files are in:

        C:\Program Files\MySQL\MySQL Connector C 6.1\

    There are a number of reasons why that path may not work for you:

      - You have a newer version of Connector/C installed

      - You're on a 64-bit system, but have the 32-bit versions of
        Connector/C and MinGW installed and wish to build a 32-bit
        binary.  In that case, the path will look like this instead:

          C:\Program Files (x86)\MySQL\MySQL Connector C 6.1\

      - You may have the MySQL Server on your system and installed the
        development files along with it, and therefore don't want to
        install Connector/C separately.  In that case, the path will
        look like this instead:

          C:\Program Files\MySQL\MySQL Server 5.6\
    
    Regardless of the reason you have for changing this path, there are
    two ways that work:

      - The easy way is to do a global search and replace on the path
        in Makefile.mingw.  This is a generated file, but if that's the
        only change to MySQL++ you need, it works fine.

      - If you're doing deeper work on MySQL++, you should change the

        MYSQL_WIN_DIR variable at the top of mysql++.bkl instead.

        
        Having done that, you can generate Makefile.mingw from that
        file using the Windows port of Bakefile (http://bakefile.org/):




        
          bakefile_gen -f mingw


Building the Library and Example Programs
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    With the prerequisites above taken care of, you can build MySQL++
    with this command:

        mingw32-make -f Makefile.mingw

    Notice that we're using the MinGW-specific version of GNU make, not
    the Cygwin or MSYS versions.  Many things will break otherwise: path
    separator handling, shell commands used by the Makefile, etc.

    Speaking of Cygwin and MSYS, if you have either these or any other
    Unix emulation environment installed, be sure their executables
    aren't in the PATH when building MySQL++.  MinGW's version of GNU
    make does some funny things if it thinks it's running in the
    presence of Unixy tools, which will break the MySQL++ build.

    Once the library is built, you should run the examples.  At minimum,
    run resetdb and simple1.

    Once you're satisfied that the library is working correctly, you can
    run install.hta to automatically install the library files and
    headers in subdirectories under c:\mysql++.


Cygwin and MinGW Coexistence
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    It's possible to have both Cygwin and MinGW installed and build
    with the MinGW tools without interference from the Cygwin bits.
    The main thing you have to take care of is that MinGW's bin
    directory must precede the Cygwin bin directory in the PATH,
    so that its tools are found first.  If you use Cygwin's bash
    as a command shell in preference to the DOS-like cmd.exe, you
    can use this shell script to temporarily set the environment to
    "MinGW mode" and make it easy to get back to "Cygwin mode":


        #!/bin/sh
        PATH=/c/mingw/bin:/c/windows:/c/windows/system32:/c/cygwin/bin
        echo "Say 'exit' to leave MinGW shell and restore Cygwin environment."
        /usr/bin/bash --rcfile ~/.mingwrc


    I recommend having at least this in the ~/.mingwrc file:

        alias make=mingw32-make
        PS1='MinGW: \W \$ '

    The prompt change reminds you that you are in a sub-shell set up for
    MinGW.  The alias for 'make' ensures you don't accidentally run
    Cygwin's make, which won't work with Makefile.mingw.  We could just
    leave /c/cygwin/bin out of the environment, but there are Cygwin
    tools we want access to, like vim.  As long as all the MinGW ones
    override those Cygwin also provides, we don't need to worry about
    having both in the PATH.  Besides, having the alias is nice for
    those who have 'make' committed to muscle memory.



Building on Linux
~~~~~~~~~~~~~~~~~
    You might wish to build MySQL++ with MinGW because you're
    not actually running Windows, but need Windows executables.
    The thought being that this lets you use GCC, the same compiler
    you're probably using to make native executables.  There are
    indeed ways to make this work.

    The most "native" way to do this is to run MinGW under Wine.
    Leonti Bielski provided these instructions:

        1. Install MinGW through Wine:


           $ wine MinGW-5.1.6.exe





        2. Add the MinGW directory to Wine's PATH with Wine regedit:


           http://winehq.org/site/docs/wineusr-guide/environment-variables

        3. Install MySQL under Wine, or at least unpack the Windows
           ZIP file version of MySQL in a place where Wine can find it.
           You don't need to run a Windows MySQL server under Wine.
           We're only doing this to get the MySQL C API library and
           its headers, which MySQL++ builds against.  The resulting
           MinGW build of MySQL++ can talk to a native MySQL server
           out in Wine's host environment or on some other machine.



        4. Modify Makefile.mingw to match the install location for
           the MySQL C API files.






        5. Build MySQL++ with:
        
           $ wine mingw32-make -f Makefile.mingw

    Another way is to build a Windows virtual machine, such as with
    VMware or VirtualBox.  In that case, you'd use the regular build
    instructions at the top of this document.

    You might think to avoid the need for Wine or Windows by use of a
    MinGW cross-compiler:

        $ ./configure --target=mingw32
        $ make

    Unfortunately, that currently doesn't work.

    The reason is that our autoconf build system assumes a
    typical POSIX type target, which MinGW is not.  We made this
    assumption because we have a perfectly good MinGW build option,
    Makefile.mingw.  But, that also won't work on a POSIX system
    because that Makefile assumes external commands run under cmd.exe,
    not some Unixy shell.  Thus the advice to build with Makefile.mingw
    under Windows or something sufficiently close to it.

    If you really wanted to, you could extend the autoconf build system
    to make it realize when it's being used to cross-compile for MinGW.
    Patches thoughtfully considered; see HACKERS.txt.

Changes to lib/sql_buffer.cpp.





1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26

27
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
56














































57

58








59





60



61




62





63





64


65


66


67


68


69


70




71


72





73





74





75




























76

77








78








79






80

















81



82


83


84


85


86


87


88




89

























90
91
92





/***********************************************************************
 sql_buffer.cpp - Implements the SQLBuffer class.

 Copyright (c) 2007-2008 by Educational Technology Resources, Inc.
 Others may also hold copyrights on code in this file.  See the
 CREDITS.txt file in the top directory of the distribution for details.

 This file is part of MySQL++.

 MySQL++ is free software; you can redistribute it and/or modify it
 under the terms of the GNU Lesser General Public License as published
 by the Free Software Foundation; either version 2.1 of the License, or
 (at your option) any later version.

 MySQL++ is distributed in the hope that it will be useful, but WITHOUT
 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
 License for more details.

 You should have received a copy of the GNU Lesser General Public
 License along with MySQL++; if not, write to the Free Software
 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
 USA
***********************************************************************/

#include "sql_buffer.h"


#include "datetime.h"

#include "sql_types.h"

#include <string.h>


namespace mysqlpp {























SQLBuffer&




















SQLBuffer::assign(const char* data, size_type length, mysql_type_info type,












		bool is_null)






{












	replace_buffer(data, length);


	type_ = type;





	is_null_ = is_null;


	return *this;


}















SQLBuffer&


SQLBuffer::assign(const std::string& s, mysql_type_info type, bool is_null)


{


	replace_buffer(s.data(), s.length());





	type_ = type;


	is_null_ = is_null;










	return *this;
}























bool
SQLBuffer::quote_q() const














































{

	if ((type_.base_type().c_type() == typeid(mysqlpp::sql_datetime)) &&








			data_ && (length_ >= 5) && (memcmp(data_, "NOW()", 5) == 0)) {





		// The default DATETIME value is special-cased as a call to the



		// SQL NOW() function, which must not be quoted.




		return false;





	}





	else {


		// Normal case: we can infer the need to quote from the type.


		return type_.quote_q();


	}


}





void




SQLBuffer::replace_buffer(const char* pd, size_type length)


{





	delete[] data_;





	data_ = 0;





	length_ = 0;






























	if (pd) {








		// The casts for the data member are because the C type system








		// can't distinguish initialization from modification when it






		// happens in 2 steps like this.

















		// 



		// We cast away const for pd in case we're on a system that uses


		// the old definition of memcpy() with non-const 2nd parameter.


		data_ = new char[length + 1];


		length_ = length;


		memcpy(const_cast<char*>(data_), const_cast<char*>(pd), length_);


		const_cast<char*>(data_)[length_] = '\0';


	}




}


























} // end namespace mysqlpp


>
>
>
>

<
|
|
|
|



















|
>

|
>
|

|
>



>
>
>
>
>
>

>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
|
>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
|
>
>
|
>
>
>
>
>
|
>
>
|
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>

>
>
|
>
>
|
>
>
|
>
>
|
>
>
>
>
>
|
>
>
|
>
>
>
>
>
>
>
>
>
>
|
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

>
>
|
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
|
>
>
>
>
>
>
>
>
|
>
>
>
>
>
|
>
>
>
|
>
>
>
>
|
>
>
>
>
>
|
>
>
>
>
>
|
>
>
|
>
>
|
>
>
|
>
>
|
>
>

>
>
|
>
>
>
>
|
>
>
|
>
>
>
>
>
|
>
>
>
>
>
|
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
|
>
>
>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
|
>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
>
>
|
>
>
|
>
>
|
>
>
|
>
>
|
>
>
|
>
>
|
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>



>
1
2
3
4
5

6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
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
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
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
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
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
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
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
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
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
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
/// \file datetime.h
/// \brief Declares classes to add SQL-compatible date and time
/// types to C++'s type system.

/***********************************************************************

 Copyright (c) 1998 by Kevin Atkinson, (c) 1999-2001 by MySQL AB, and
 (c) 2004-2008 by Educational Technology Resources, Inc.  Others may
 also hold copyrights on code in this file.  See the CREDITS.txt file
 in the top directory of the distribution for details.

 This file is part of MySQL++.

 MySQL++ is free software; you can redistribute it and/or modify it
 under the terms of the GNU Lesser General Public License as published
 by the Free Software Foundation; either version 2.1 of the License, or
 (at your option) any later version.

 MySQL++ is distributed in the hope that it will be useful, but WITHOUT
 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
 License for more details.

 You should have received a copy of the GNU Lesser General Public
 License along with MySQL++; if not, write to the Free Software
 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
 USA
***********************************************************************/

#if !defined(MYSQLPP_DATETIME_H)
#define MYSQLPP_DATETIME_H

#include "common.h"

#include "comparable.h"

#include <string>
#include <iostream>

namespace mysqlpp {

/// \brief C++ form of SQL's DATETIME type.
///
/// This object exists primarily for conversion purposes.  You can
/// initialize it in several different ways, and then convert the object
/// to SQL string form, extract the individual y/m/d h:m:s values,
/// convert it to C's time_t, etc.

class MYSQLPP_EXPORT DateTime : public Comparable<DateTime>
{
public:
	/// \brief Default constructor
	DateTime() :
	Comparable<DateTime>(),
	year_(0),
	month_(0),
	day_(0),
	hour_(0),
	minute_(0),
	second_(0),
	now_(true)
	{
	}

	/// \brief Initialize object from discrete y/m/d h:m:s values.
	///
	/// \param y year, 1000-9999
	/// \param mon month, 1-12
	/// \param d day of month, 1-31
	/// \param h hour, 0-23
	/// \param min minute, 0-59
	/// \param s second, 0-59
	DateTime(unsigned short y, unsigned char mon, unsigned char d,
			unsigned char h, unsigned char min, unsigned char s) :
	Comparable<DateTime>(),
	year_(y),
	month_(mon),
	day_(d),
	hour_(h),
	minute_(min),
	second_(s),
	now_(false)
	{
	}
	
	/// \brief Initialize object as a copy of another Date
	DateTime(const DateTime& other) :
	Comparable<DateTime>(),
	year_(other.year_),
	month_(other.month_),
	day_(other.day_),
	hour_(other.hour_),
	minute_(other.minute_),
	second_(other.second_),
	now_(other.now_)
	{
	}

	/// \brief Initialize object from a C string containing a SQL
	/// date-and-time string
	///
	/// String must be in the HH:MM:SS format.  It doesn't have to be
	/// zero-padded.
	explicit DateTime(const char* str) { convert(str); }
	
	/// \brief Initialize object from a C++ string containing a
	/// SQL date-and-time string
	///
	/// This works with any stringish class that declares a c_str()
	/// member function: std::string, mysqlpp::String...
	///
	/// \sa DateTime(const char*)
	template <class Str>
	explicit DateTime(const Str& str)
	{
		convert(str.c_str());
	}

	/// \brief Initialize object from a \c time_t
	explicit DateTime(time_t t);

	/// \brief Compare this object to another.
	///
	/// Returns < 0 if this object is before the other, 0 of they are
	/// equal, and > 0 if this object is after the other.
	int compare(const DateTime& other) const;

	/// \brief Parse a SQL date and time string into this object.
	const char* convert(const char*);

	/// \brief Get the date/time value's day part, 1-31
	unsigned char day() const { return day_; }

	/// \brief Change the date/time value's day part, 1-31
	void day(unsigned char d) { day_ = d; now_ = false; }

	/// \brief Get the date/time value's hour part, 0-23
	unsigned char hour() const { return hour_; }

	/// \brief Change the date/time value's hour part, 0-23
	void hour(unsigned char h) { hour_ = h; now_ = false; }

	/// \brief Returns true if object will evaluate to SQL "NOW()" on
	/// conversion to string.
	bool is_now() const { return now_; }

	/// \brief Get the date/time value's minute part, 0-59
	unsigned char minute() const { return minute_; }

	/// \brief Change the date/time value's minute part, 0-59
	void minute(unsigned char m) { minute_ = m; now_ = false; }

	/// \brief Get the date/time value's month part, 1-12
	unsigned char month() const { return month_; }

	/// \brief Change the date/time value's month part, 1-12
	void month(unsigned char m) { month_ = m; now_ = false; }

	/// \brief Factory to create an object instance that will convert
	/// to SQL "NOW()" on insertion into a query
	///
	/// This is just syntactic sugar around the default ctor
	static DateTime now() { return DateTime(); }

	/// \brief Convert to std::string
	operator std::string() const;

	/// \brief Convert to time_t
	operator time_t() const;

	/// \brief Get the date/time value's second part, 0-59
	unsigned char second() const { return second_; }

	/// \brief Change the date/time value's second part, 0-59
	void second(unsigned char s) { second_ = s; now_ = false; }

	/// \brief Return our value in std::string form
	std::string str() const { return *this; }

	/// \brief Get the date/time value's year part
	///
	/// There's no trickery here like in some date/time implementations
	/// where you have to add 1900 or something like that.  It simply
	/// returns the year in natural form, in the range 1000-9999.
	unsigned short year() const { return year_; }

	/// \brief Change the date/time value's year part
	///
	/// Pass the year value normally; we don't optimize the value by
	/// subtracting 1900 like some other date/time implementations.
	void year(unsigned short y) { year_ = y; now_ = false; }

private:
	unsigned short year_;	///< the year, as a simple integer
	unsigned char month_;	///< the month, 1-12
	unsigned char day_;		///< the day, 1-31
	unsigned char hour_;	///< the hour, 0-23 (not 0-255 as in Time!)
	unsigned char minute_;	///< the minute, 0-59
	unsigned char second_;	///< the second, 0-59

	bool now_;	///< true if object not initialized with explicit value
};


/// \brief Returns a DateTime object that, when inserted into query
/// will yield a SQL "NOW()" function call.
inline DateTime NOW() { return DateTime(); }


/// \brief Inserts a DateTime object into a C++ stream in a
/// SQL-compatible format.
///
/// The date and time are inserted into the stream, in that order,
/// with a space between them.
///
/// \param os stream to insert date and time into
/// \param dt date/time object to insert into stream
MYSQLPP_EXPORT std::ostream& operator <<(std::ostream& os,
		const DateTime& dt);


/// \brief C++ form of SQL's DATE type.
///
/// Objects of this class can be inserted into streams, and
/// initialized from SQL DATE strings.
class MYSQLPP_EXPORT Date : public Comparable<Date>
{
public:
	/// \brief Default constructor
	Date() : year_(0), month_(0), day_(0) { }

	/// \brief Initialize object
	///
	/// \param y year, 1000-9999
	/// \param m month, 1-12
	/// \param d day of month, 1-31
	Date(unsigned short y, unsigned char m, unsigned char d) :
	Comparable<Date>(),
	year_(y),
	month_(m),
	day_(d)
	{
	}
	
	/// \brief Initialize object as a copy of another Date
	Date(const Date& other) :
	Comparable<Date>(),
	year_(other.year_),
	month_(other.month_),
	day_(other.day_)
	{
	}

	/// \brief Initialize object from date part of date/time object
	Date(const DateTime& other) :
	Comparable<Date>(),
	year_(other.year()),
	month_(other.month()),
	day_(other.day())
	{
	}

	/// \brief Initialize object from a C string containing a date
	///
	/// String must be in the YYYY-MM-DD format.  It doesn't have to be
	/// zero-padded.
	explicit Date(const char* str) { convert(str); }
	
	/// \brief Initialize object from a C++ string containing a date
	///
	/// This works with any stringish class that declares a c_str()
	/// member function: std::string, mysqlpp::String...
	///
	/// \sa Date(const char*)
	template <class Str>
	explicit Date(const Str& str) { convert(str.c_str()); }

	/// \brief Initialize object from a \c time_t
	///
	/// Naturally, we throw away the "time" part of the \c time_t.  If
	/// you need to keep it, you want to use DateTime instead.
	explicit Date(time_t t);

	/// \brief Compare this date to another.
	///
	/// Returns < 0 if this date is before the other, 0 of they are
	/// equal, and > 0 if this date is after the other.
	int compare(const Date& other) const;

	/// \brief Parse a SQL date string into this object.
	const char* convert(const char*);

	/// \brief Get the date's day part, 1-31
	unsigned char day() const { return day_; }

	/// \brief Change the date's day part, 1-31
	void day(unsigned char d) { day_ = d; }

	/// \brief Get the date's month part, 1-12
	unsigned char month() const { return month_; }

	/// \brief Change the date's month part, 1-12
	void month(unsigned char m) { month_ = m; }

	/// \brief Convert to std::string
	operator std::string() const;

	/// \brief Convert to time_t
	///
	/// The "time" part of the \c time_t is "now"
	operator time_t() const;

	/// \brief Return our value in std::string form
	std::string str() const { return *this; }

	/// \brief Get the date's year part
	///
	/// There's no trickery here like in some date implementations
	/// where you have to add 1900 or something like that.
	unsigned short year() const { return year_; }

	/// \brief Change the date's year part
	///
	/// Pass the year value normally; we don't optimize the value by
	/// subtracting 1900 like some other date implementations.
	void year(unsigned short y) { year_ = y; }

private:
	unsigned short year_;	///< the year, as a simple integer, 1000-9999
	unsigned char month_;	///< the month, 1-12
	unsigned char day_;		///< the day, 1-31
};

/// \brief Inserts a Date object into a C++ stream
///
/// The format is YYYY-MM-DD, zero-padded.
///
/// \param os stream to insert date into
/// \param d date to insert into stream
MYSQLPP_EXPORT std::ostream& operator <<(std::ostream& os,
		const Date& d);


/// \brief C++ form of SQL's TIME type.
///
/// Objects of this class can be inserted into streams, and
/// initialized from SQL TIME strings.
class MYSQLPP_EXPORT Time : public Comparable<Time>
{
public:
	/// \brief Default constructor
	Time() : hour_(0), minute_(0), second_(0) { }

	/// \brief Initialize object
	/// \param h hour, 0-255 (yes, > 1 day is legal in SQL!)
	/// \param m minute, 0-59
	/// \param s second, 0-59
	Time(unsigned char h, unsigned char m, unsigned char s) :
	hour_(h),
	minute_(m),
	second_(s)
	{
	}

	/// \brief Initialize object as a copy of another Time
	Time(const Time& other) :
	Comparable<Time>(),
	hour_(other.hour_),
	minute_(other.minute_),
	second_(other.second_)
	{
	}

	/// \brief Initialize object from time part of date/time object
	Time(const DateTime& other) :
	Comparable<Time>(),
	hour_(other.hour()),
	minute_(other.minute()),
	second_(other.second())
	{
	}

	/// \brief Initialize object from a C string containing a SQL
	/// time string
	///
	/// String must be in the HH:MM:SS format.  It doesn't have to be
	/// zero-padded.
	explicit Time(const char* str) { convert(str); }

	/// \brief Initialize object from a C++ string containing a
	/// SQL time string
	///
	/// This works with any stringish class that declares a c_str()
	/// member function: std::string, mysqlpp::String...
	///
	/// \sa Time(const char*)
	template <class Str>
	explicit Time(const Str& str) { convert(str.c_str()); }

	/// \brief Initialize object from a \c time_t
	///
	/// Naturally, we throw away the "date" part of the \c time_t.  If
	/// you need to keep it, you want to use DateTime instead.
	explicit Time(time_t t);

	/// \brief Compare this time to another.
	///
	/// Returns < 0 if this time is before the other, 0 of they are
	/// equal, and > 0 if this time is after the other.
	int compare(const Time& other) const;

	/// \brief Parse a SQL time string into this object.
	const char* convert(const char*);

	/// \brief Get the time's hour part, 0-255
	unsigned char hour() const { return hour_; }

	/// \brief Change the time's hour part, 0-255
	void hour(unsigned char h) { hour_ = h; }

	/// \brief Get the time's minute part, 0-59
	unsigned char minute() const { return minute_; }

	/// \brief Change the time's minute part, 0-59
	void minute(unsigned char m) { minute_ = m; }

	/// Convert to std::string
	operator std::string() const;

	/// \brief Convert to time_t
	///
	/// The "date" part of the \c time_t is "today"
	operator time_t() const;

	/// \brief Get the time's second part, 0-59
	unsigned char second() const { return second_; }

	/// \brief Change the time's second part, 0-59
	void second(unsigned char s) { second_ = s; }

	/// Return our value in std::string form
	std::string str() const { return *this; }

private:
	unsigned char hour_;	///< the hour, 0-255 (yes, > 1 day is legal SQL!)
	unsigned char minute_;	///< the minute, 0-59
	unsigned char second_;	///< the second, 0-59
};

/// \brief Inserts a Time object into a C++ stream in a SQL-compatible
/// format.
///
/// The format is HH:MM:SS, zero-padded.
///
/// \param os stream to insert time into
/// \param t time to insert into stream
MYSQLPP_EXPORT std::ostream& operator <<(std::ostream& os,
		const Time& t);


} // end namespace mysqlpp

#endif // !defined(MYSQLPP_DATETIME_H)

Changes to lib/sql_buffer.h.

1
2



3
4

5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
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



56
57

58
59
60
61
62



63

64
65




66





67


68
69
70
71


72

73
74







75


76


77

78
79





80





81

82
83


84
85
86
87


88




89





90
91


92
93
94

95

96

97
98
99
100
101









102



103
104
105
106
107

108

109





110




111

112




113
114
115


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
/// \file sql_buffer.h
/// \brief Declares the SQLBuffer class




/***********************************************************************

 Copyright (c) 2007-2008 by Educational Technology Resources, Inc. and
 (c) 2007 by Jonathan Wakely.  Others may also hold copyrights on
 code in this file.  See the CREDITS.txt file in the top directory
 of the distribution for details.

 This file is part of MySQL++.

 MySQL++ is free software; you can redistribute it and/or modify it
 under the terms of the GNU Lesser General Public License as published
 by the Free Software Foundation; either version 2.1 of the License, or
 (at your option) any later version.

 MySQL++ is distributed in the hope that it will be useful, but WITHOUT
 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
 License for more details.

 You should have received a copy of the GNU Lesser General Public
 License along with MySQL++; if not, write to the Free Software
 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
 USA
***********************************************************************/

#if !defined(MYSQLPP_SQL_BUFFER_H)
#define MYSQLPP_SQL_BUFFER_H

#include "refcounted.h"
#include "type_info.h"


#include <string>



namespace mysqlpp {

/// \brief Holds SQL data in string form plus type information for use
/// in converting the string to compatible C++ data types.

class SQLBuffer
{
public:
	/// \brief Type of length values





	typedef size_t size_type;






	/// \brief Initialize object as a copy of a raw data buffer
	///

	/// Copies the string into a new buffer one byte longer than





	/// the length value given, using that to hold a C string null






	/// terminator, just for safety.  The length value we keep does
	/// not include this extra byte, allowing this same mechanism
	/// to work for both C strings and binary data.
	SQLBuffer(const char* data, size_type length, mysql_type_info type,



			bool is_null) : data_(), length_(), type_(type),



			is_null_(is_null)
			{ replace_buffer(data, length); }


	/// \brief Initialize object as a copy of a C++ string object
	SQLBuffer(const std::string& s, mysql_type_info type, bool is_null) :
			data_(), length_(), type_(type), is_null_(is_null)
	{



		replace_buffer(s.data(), static_cast<size_type>(s.length()));

	}





	/// \brief Destructor





	~SQLBuffer() { delete[] data_; }



	/// \brief Replace contents of buffer with copy of given C string
	SQLBuffer& assign(const char* data, size_type length,
			mysql_type_info type = mysql_type_info::string_type,


			bool is_null = false);


	/// \brief Replace contents of buffer with copy of given C++ string







	SQLBuffer& assign(const std::string& s,


			mysql_type_info type = mysql_type_info::string_type,


			bool is_null = false);


	/// \brief Return pointer to raw data buffer





	const char* data() const { return data_; }







	/// \brief Returns true if we were initialized with a data type
	/// that must be escaped when used in a SQL query


	bool escape_q() const { return type_.escape_q(); }

	/// \brief Return number of bytes in data buffer
	///


	/// Count does not include the trailing null we tack on to our




	/// copy of the buffer for ease of use in C string contexts.





	/// We do this because we can be holding binary data just as
	/// easily as a C string.


	size_type length() const { return length_; }

	/// \brief Returns true if type of buffer's contents is string

	bool is_string() { return type_ == mysql_type_info::string_type; }



	/// \brief Return true if buffer's contents represent a SQL
	/// null.
	///
	/// The buffer's actual content will probably be "NULL" or
	/// something like it, but in the SQL data type system, a SQL









	/// null is distinct from a plain string with value "NULL".



	bool is_null() const { return is_null_; }

	/// \brief Returns true if we were initialized with a data type
	/// that must be quoted when used in a SQL query
	bool quote_q() const;



	/// \brief Sets the internal SQL null flag





	void set_null() { is_null_ = true; }






	/// \brief Return the SQL type of the data held in the buffer




	const mysql_type_info& type() const { return type_; }

private:


	SQLBuffer(const SQLBuffer&);
	SQLBuffer& operator=(const SQLBuffer&);













	/// \brief Common initialization for ctors



	void init(const char* pd, size_type len, mysql_type_info type,


			bool is_null);









	/// \brief Implementation detail of assign() and init()
	void replace_buffer(const char* pd, size_type length);

























































































	const char* data_;		///< pointer to the raw data buffer
	size_type length_;		///< bytes in buffer, without trailing null


	mysql_type_info type_;	///< SQL type of data in the buffer












	bool is_null_;			///< if true, string represents a SQL null




























































































};


/// \brief Reference-counted version of SQLBuffer.
///
/// No one uses SQLBuffer directly.  It exists only for use in a
/// RefCountedPointer wrapper.
typedef RefCountedPointer<SQLBuffer> RefCountedBuffer;

} // end namespace mysqlpp

#endif // !defined(MYSQLPP_SQL_BUFFER_H)

|
|
>
>
>


>
|
<
|
|



















|
|

|
<

>

>
>



|
<

|


|
>
>
>
>
>
|
>
>
|
>
>
>
|
|
>
|
>
>
>
>
>
|
>
>
>
>
>
>
|
<
|
|
>
>
>
|
>
>
>
|
|
>

<
|
<
|
>
>
>
|
>
|
|
>
>
>
>
|
>
>
>
>
>
|
>
>
|
<
<
<
>
>
|
>
|
|
>
>
>
>
>
>
>
|
>
>
|
>
>
|
>
|
|
>
>
>
>
>
|
>
>
>
>
>
|
>
|
|
>
>
|

|
|
>
>
|
>
>
>
>
|
>
>
>
>
>
|
|
>
>
|

|
>
|
>
|
>
|
<

|
|
>
>
>
>
>
>
>
>
>
|
>
>
>
|

|
|
|
>
|
>
|
>
>
>
>
>
|
>
>
>
>
|
>
|
>
>
>
>
|


>
>
|
|
>
>
>
>

>
>
>
>
>
>
>
>
|
>
>
>
|
>
>
|
>
>
>
>
>
>
>
>
>
|
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
>
>
|
|
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>



<
<
<
<
<
<


|
<
1
2
3
4
5
6
7
8
9

10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
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
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77

78
79
80
81
82
83
84
85
86
87
88
89
90

91

92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113



114
115
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
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
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
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
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
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
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
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466






467
468
469

/// \file exceptions.h
/// \brief Declares the MySQL++-specific exception classes.
///
/// When exceptions are enabled for a given mysqlpp::OptionalExceptions
/// derivative, any of these exceptions can be thrown on error.

/***********************************************************************
 Copyright (c) 1998 by Kevin Atkinson, (c) 1999-2001 by MySQL AB, and
 (c) 2004-2010 by Educational Technology Resources, Inc.  Others may

 also hold copyrights on code in this file.  See the CREDITS.txt file
 in the top directory of the distribution for details.

 This file is part of MySQL++.

 MySQL++ is free software; you can redistribute it and/or modify it
 under the terms of the GNU Lesser General Public License as published
 by the Free Software Foundation; either version 2.1 of the License, or
 (at your option) any later version.

 MySQL++ is distributed in the hope that it will be useful, but WITHOUT
 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
 License for more details.

 You should have received a copy of the GNU Lesser General Public
 License along with MySQL++; if not, write to the Free Software
 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
 USA
***********************************************************************/

#if !defined(MYSQLPP_EXCEPTIONS_H)
#define MYSQLPP_EXCEPTIONS_H

#include "options.h"


#include <exception>
#include <string>
#include <sstream>
#include <typeinfo>

namespace mysqlpp {

/// \brief Base class for all MySQL++ custom exceptions


class MYSQLPP_EXPORT Exception : public std::exception
{
public:
	/// \brief Create exception object as copy of another
	Exception(const Exception& e) throw() :
	std::exception(e),
	what_(e.what_)
	{
	}

	/// \brief Assign another exception object's contents to this one
	Exception& operator=(const Exception& rhs) throw()
	{
		what_ = rhs.what_;
		return *this;
	}

	/// \brief Destroy exception object
	~Exception() throw() { }

	/// \brief Returns explanation of why exception was thrown
	virtual const char* what() const throw()
	{
		return what_.c_str();
	}

protected:
	/// \brief Create exception object
	Exception(const char* w = "") throw() :
	what_(w)
	{
	}


	/// \brief Create exception object
	Exception(const std::string& w) throw() :
	what_(w)
	{
	}

	/// \brief explanation of why exception was thrown
	std::string what_;
};


/// \brief Exception thrown when a bad type conversion is attempted.


class MYSQLPP_EXPORT BadConversion : public Exception

{
public:
	const char* type_name;	///< name of type we tried to convert to
	std::string data;		///< string form of data we tried to convert
	size_t retrieved;		///< documentation needed!
	size_t actual_size;		///< documentation needed!

	/// \brief Create exception object, building error string
	/// dynamically
	///
	/// \param tn type name we tried to convert to
	/// \param d string form of data we tried to convert
	/// \param r ??
	/// \param a ??
	BadConversion(const char* tn, const char* d,
			size_t r, size_t a) :
	Exception("Bad type conversion: \""),
	type_name(tn),
	data(d),
	retrieved(r),
	actual_size(a)
	{



		what_ += d ? d : "<NULL>";
		what_ += "\" incompatible with \"";
		what_ += tn;
		what_ += "\" type";
	}

	/// \brief Create exception object, given completed error string
	///
	/// \param w the "what" error string
	/// \param tn type name we tried to convert to
	/// \param d string form of data we tried to convert
	/// \param r ??
	/// \param a ??
	BadConversion(const std::string& w, const char* tn,
				  const char* d, size_t r, size_t a) :
	Exception(w),
	type_name(tn),
	data(d),
	retrieved(r),
	actual_size(a)
	{
	}

	/// \brief Create exception object, with error string only
	///
	/// \param w the "what" error string
	///
	/// All other data members are initialize to default values
	explicit BadConversion(const char* w = "") :
	Exception(w),
	type_name("unknown"),
	data(""),
	retrieved(0),
	actual_size(0)
	{
	}

	/// \brief Destroy exception
	~BadConversion() throw() { }
};


/// \brief Exception thrown when a requested named field doesn't exist.
///
/// Thrown by Row::lookup_by_name() when you pass a field name that
/// isn't in the result set.

class MYSQLPP_EXPORT BadFieldName : public Exception
{
public:
	/// \brief Create exception object
	///
	/// \param bad_field name of field the database server didn't like
	explicit BadFieldName(const char* bad_field) :
	Exception(std::string("Unknown field name: ") + bad_field)
	{
	}

	/// \brief Destroy exception
	~BadFieldName() throw() { }
};


/// \brief Exception thrown when an object with operator [] or an
/// at() method gets called with a bad index.

class MYSQLPP_EXPORT BadIndex : public Exception
{
public:
	/// \brief Create exception object

	///
	/// \param what type of object bad index tried on
	/// \param bad_index index value the container didn't like
	/// \param max_index largest legal index value for container
	explicit BadIndex(const char* what, int bad_index, int max_index) :
	Exception()
	{
		std::ostringstream outs;
		outs << "Index " << bad_index << " on " << what <<
				" out of range, max legal index is " << max_index;
		what_ = outs.str();
	}

	/// \brief Destroy exception
	~BadIndex() throw() { }
};


/// \brief Exception thrown when you pass an unrecognized option to
/// Connection::set_option().

class MYSQLPP_EXPORT BadOption : public Exception
{
public:
	/// \brief Create exception object, taking C string
	explicit BadOption(const char* w, const std::type_info& ti) :
	Exception(w),
	ti_(ti)
	{
	}

	/// \brief Create exception object, taking C++ string
	explicit BadOption(const std::string& w, const std::type_info& ti) :
	Exception(w),
	ti_(ti)
	{
	}

	/// \brief Return type information about the option that failed
	///
	/// Because each option has its own C++ type, this lets you
	/// distinguish among BadOption exceptions programmatically.
	const std::type_info& what_option() const { return ti_; }

private:
	const std::type_info& ti_;
};


/// \brief Exception thrown when not enough query parameters are
/// provided.
///
/// This is used in handling template queries.

class MYSQLPP_EXPORT BadParamCount : public Exception
{
public:
	/// \brief Create exception object
	explicit BadParamCount(const char* w = "") :
	Exception(w)
	{
	}

	/// \brief Destroy exception
	~BadParamCount() throw() { }
};

/// \brief Exception thrown when something goes wrong in processing a
/// "use" query.

class MYSQLPP_EXPORT UseQueryError : public Exception
{
public:
	/// \brief Create exception object
	explicit UseQueryError(const char* w = "") :
	Exception(w)
	{
	}
};


/// \brief Exception thrown when the database server encounters a problem
/// while processing your query.
///
/// Unlike most other MySQL++ exceptions, which carry just an error
/// message, this type carries an error number to preserve
/// Connection::errnum()'s return value at the point the exception is 
/// thrown.  We do this because when using the Transaction class, the
/// rollback process that occurs during stack unwinding issues a query
/// to the database server, overwriting the error value.  This rollback
/// should always succeed, so this effect can fool code that relies on
/// Connection::errnum() into believing that there was no error.
///
/// Beware that in older versions of MySQL++, this was effectively the
/// generic exception type.  (This is most especially true in v1.7.x,
/// but it continued to a lesser extent through the v2.x series.)  When
/// converting old code to new versions of MySQL++, it's therefore
/// possible to get seemingly "new" exceptions thrown, which could crash
/// your program if you don't also catch a more generic type like
/// mysqlpp::Exception or std::exception.

class MYSQLPP_EXPORT BadQuery : public Exception
{
public:
	/// \brief Create exception object
	///
	/// \param w explanation for why the exception was thrown
	/// \param e the error number from the underlying database API
	explicit BadQuery(const char* w = "", int e = 0) :
	Exception(w),
	errnum_(e)
	{
	}

	/// \brief Create exception object
	///
	/// \param w explanation for why the exception was thrown
	/// \param e the error number from the underlying database API
	explicit BadQuery(const std::string& w, int e = 0) :
	Exception(w),
	errnum_(e)
	{
	}

	/// \brief Return the error number corresponding to the error
	/// message returned by what()
	///
	/// This may return the same value as Connection::errnum(), but not
	/// always.  See the overview documentation for this class for the
	/// reason for the difference.
	int errnum() const { return errnum_; }
	
private:	
	int	errnum_;	///< error number associated with execption
};


/// \brief Exception thrown when there is a problem related to the
/// database server connection.
///
/// This is thrown not just on making the connection, but also on
/// shutdown and when calling certain of Connection's methods that
/// require a connection when there isn't one.

class MYSQLPP_EXPORT ConnectionFailed : public Exception
{
public:
	/// \brief Create exception object
	///
	/// \param w explanation for why the exception was thrown
	/// \param e the error number from the underlying database API
	explicit ConnectionFailed(const char* w = "", int e = 0) :
	Exception(w),
	errnum_(e)
	{
	}

	/// \brief Return the error number corresponding to the error
	/// message returned by what(), if any.
	///
	/// If the error number is 0, it means that the error message
	/// doesn't come from the underlying database API, but rather from
	/// MySQL++ itself.  This happens when an error condition is
	/// detected up at this higher level instead of letting the
	/// underlying database API do it.
	int errnum() const { return errnum_; }
	
private:	
	int	errnum_;	///< error number associated with execption
};


/// \brief Exception thrown when the program tries to select a new
/// database and the database server refuses for some reason.

class MYSQLPP_EXPORT DBSelectionFailed : public Exception
{
public:
	/// \brief Create exception object
	///
	/// \param w explanation for why the exception was thrown
	/// \param e the error number from the underlying database API
	explicit DBSelectionFailed(const char* w = "", int e = 0) :
	Exception(w),
	errnum_(e)
	{
	}

	/// \brief Return the error number corresponding to the error
	/// message returned by what(), if any.
	///
	/// If the error number is 0, it means that the error message
	/// doesn't come from the underlying database API, but rather from
	/// MySQL++ itself.  This happens when an error condition is
	/// detected up at this higher level instead of letting the
	/// underlying database API do it.
	int errnum() const { return errnum_; }
	
private:	
	int	errnum_;	///< error number associated with execption
};


/// \brief Exception thrown when a BeecryptMutex object fails.

class MYSQLPP_EXPORT MutexFailed : public Exception
{
public:
	/// \brief Create exception object
	explicit MutexFailed(const char* w = "lock failed") :
	Exception(w)
	{
	}
};


/// \brief Exception thrown when you try to use an object that isn't
/// completely initialized.

class MYSQLPP_EXPORT ObjectNotInitialized : public Exception
{
public:
	/// \brief Create exception object
	explicit ObjectNotInitialized(const char* w = "") :
	Exception(w)
	{
	}
};


/// \brief Used within MySQL++'s test harness only.

class MYSQLPP_EXPORT SelfTestFailed : public Exception
{
public:
	/// \brief Create exception object
	explicit SelfTestFailed(const std::string& w) :
	Exception(w)
	{
	}
};


/// \brief Thrown from the C++ to SQL data type conversion routine when
/// it can't figure out how to map the type.
///
/// This exception is not optional.  The only alternatives when this
/// happens are equally drastic: basically, either iterate past the
/// end of an array (crashing the program) or call assert() to crash
/// the program nicely.  At least this way you have some control over
/// how your program ends.  You can even ignore the error and keep on
/// going: this typically happens when building a SQL query, so you can
/// handle it just the same as if the subsequent query execution failed.

class MYSQLPP_EXPORT TypeLookupFailed : public Exception
{
public:
	/// \brief Create exception object
	explicit TypeLookupFailed(const std::string& w) :
	Exception(w)
	{
	}
};


/// \brief Exception thrown when an insert policy is too strict to
/// create a valid INSERT statement.
///
/// Thrown by Query::insertfrom() if it is unable to add VALUES
/// to an empty query.  This means the size threshold or max packet
/// size of the policy is set too small.

class MYSQLPP_EXPORT BadInsertPolicy : public Exception
{
public:
	/// \brief Create exception object
	explicit BadInsertPolicy(const std::string& w) :
	Exception(w)
	{
	}
};








} // end namespace mysqlpp

#endif // !defined(MYSQLPP_EXCEPTIONS_H)

Changes to lib/sql_types.h.

1
2
3
4
5
6
7
8

9
10
11


12

13
14
15
16
17
18

19
20
21
22




23

24
25
26
27
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
56
57

58
59
60
61
62
63

64
65
66
67
68
69
70
71
72
73
74
75
76

77
78


79
80
81
82
83

84
85
86
87
88
89
90


91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109

110
111

112
113

114


115
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
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
191
192
193


194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
/// \file sql_types.h
/// \brief Declares the closest C++ equivalent of each MySQL column type
///
/// The typedefs defined here are only for the "non-NULL" variants.
/// To get nullable versions, wrap the appropriate type in the
/// \c Null<T> template.  See null.h for more information.

/***********************************************************************

 Copyright (c) 2006-2009 by Educational Technology Resources, Inc.
 Others may also hold copyrights on code in this file.  See the
 CREDITS.txt file in the top directory of the distribution for details.




 This file is part of MySQL++.

 MySQL++ is free software; you can redistribute it and/or modify it
 under the terms of the GNU Lesser General Public License as published
 by the Free Software Foundation; either version 2.1 of the License, or
 (at your option) any later version.


 MySQL++ is distributed in the hope that it will be useful, but WITHOUT
 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public




 License for more details.


 You should have received a copy of the GNU Lesser General Public
 License along with MySQL++; if not, write to the Free Software
 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
 USA
***********************************************************************/



#if !defined(MYSQLPP_SQL_TYPES_H_MAIN)
#define MYSQLPP_SQL_TYPES_H_MAIN


#include "common.h"

#include "tiny_int.h"

#include <string>


#if !defined(MYSQLPP_NO_STDINT_H)
#	include <stdint.h>
#endif




namespace mysqlpp {


#if !defined(DOXYGEN_IGNORE)
// Suppress refman documentation for these typedefs, as they're
// system-dependent.







// Define C++ integer types that are most nearly equivalent to those
// used by the MySQL server.
#if defined(MYSQLPP_NO_STDINT_H)
	// Boo, we're going to have to wing it.
	typedef tiny_int<signed char>	sql_tinyint;
	typedef tiny_int<unsigned char>	sql_tinyint_unsigned;
	typedef signed short			sql_smallint;
	typedef unsigned short			sql_smallint_unsigned;
	typedef signed int				sql_int;

	typedef unsigned int			sql_int_unsigned;
	typedef signed int				sql_mediumint;
	typedef unsigned int			sql_mediumint_unsigned;
	typedef longlong				sql_bigint;
	typedef ulonglong				sql_bigint_unsigned;
#else

	// Assume a system where C99 is supported in C++ in advance of
	// actual standardization, so we can do this portably.
	typedef tiny_int<int8_t>		sql_tinyint;
	typedef tiny_int<uint8_t>		sql_tinyint_unsigned;
	typedef int16_t					sql_smallint;
	typedef uint16_t				sql_smallint_unsigned;
	typedef int32_t					sql_int;
	typedef uint32_t				sql_int_unsigned;
	typedef int32_t					sql_mediumint;
	typedef uint32_t				sql_mediumint_unsigned;
	typedef int64_t					sql_bigint;
	typedef uint64_t				sql_bigint_unsigned;
#endif


// Now define typedef equivalencies for the other standard MySQL


// data types.  There aren't serious portability issues here.
typedef float					sql_float;
typedef double					sql_double;
typedef double					sql_decimal;
typedef std::string				sql_enum;

typedef std::string				sql_char;
typedef std::string				sql_varchar;
typedef std::string				sql_tinytext;
typedef std::string				sql_text;
typedef std::string				sql_mediumtext;
typedef std::string				sql_longtext;



// Aliases to match the rules MySQL uses in translating data types
// from other database servers into its own type system.  From:
// http://dev.mysql.com/doc/refman/5.0/en/other-vendor-data-types.html
typedef sql_tinyint				sql_bool;
typedef sql_tinyint				sql_boolean;
typedef sql_varchar				sql_character_varying;
typedef sql_decimal				sql_fixed;
typedef sql_float				sql_float4;
typedef sql_double				sql_float8;
typedef sql_tinyint				sql_int1;
typedef sql_smallint			sql_int2;
typedef sql_mediumint			sql_int3;
typedef sql_int					sql_int4;
typedef sql_bigint				sql_int8;
typedef sql_mediumtext			sql_long_varchar;
typedef sql_mediumtext			sql_long;
typedef sql_mediumint			sql_middleint;
typedef sql_decimal				sql_numeric;
#endif // !defined(DOXYGEN_IGNORE)


} // end namespace mysqlpp


#endif // !defined(MYSQLPP_SQL_TYPES_H_MAIN)





// The following sections are treated separately to avoid making the
// #include tree too dense: if mystring.h (for example) is not yet
// #included, no sense pulling it in to define all the typedefs based
// on String.  The separate #include guards for each section allow
// this file to be #included as many times as necessary to build up the
// full typedef set.  This trickery is necessary because sql_types.h
// is needed in a few places within MySQL++, but we can't (and don't)
// depend on having the full set of typedefs.  mysql++.h #includes this
// at a late stage, ensuring that end-user code does see the full set.
#if defined(MYSQLPP_MYSTRING_H) && !defined(MYSQLPP_SQL_TYPES_H_MYSTRING) && !defined(DOXYGEN_IGNORE)
#	define MYSQLPP_SQL_TYPES_H_MYSTRING
	namespace mysqlpp {
		typedef String			sql_blob;
		typedef String			sql_tinyblob;
		typedef String			sql_mediumblob;
		typedef String			sql_longblob;
		typedef sql_mediumblob	sql_long_varbinary;
	} // end namespace mysqlpp
#endif








#if defined(MYSQLPP_DATETIME_H) && !defined(MYSQLPP_SQL_TYPES_H_DATETIME) && !defined(DOXYGEN_IGNORE)
#	define MYSQLPP_SQL_TYPES_H_DATETIME
	namespace mysqlpp {
		typedef Date			sql_date;
		typedef Time			sql_time;
		typedef DateTime		sql_timestamp;
		typedef DateTime		sql_datetime;
	} // end namespace mysqlpp
#endif












#if defined(MYSQLPP_MYSET_H) && !defined(MYSQLPP_SQL_TYPES_H_SET) && !defined(DOXYGEN_IGNORE)
#	define MYSQLPP_SQL_TYPES_H_SET
	namespace mysqlpp {
		typedef Set<>				sql_set;
	} // end namespace mysqlpp
#endif





#if defined(MYSQLPP_NULL_H) && !defined(MYSQLPP_SQL_TYPES_H_NULL) && !defined(DOXYGEN_IGNORE)
#	define MYSQLPP_SQL_TYPES_H_NULL
	// We have null.h, so define nullable versions of all the above
	namespace mysqlpp {
		typedef Null<sql_bigint> sql_bigint_null;

		typedef Null<sql_bigint_unsigned> sql_bigint_unsigned_null;
		typedef Null<sql_bool> sql_bool_null;
		typedef Null<sql_boolean> sql_boolean_null;
		typedef Null<sql_char> sql_char_null;
		typedef Null<sql_character_varying> sql_character_varying_null;
		typedef Null<sql_decimal> sql_decimal_null;
		typedef Null<sql_double> sql_double_null;
		typedef Null<sql_enum> sql_enum_null;
		typedef Null<sql_fixed> sql_fixed_null;
		typedef Null<sql_float> sql_float_null;
		typedef Null<sql_float4> sql_float4_null;
		typedef Null<sql_float8> sql_float8_null;
		typedef Null<sql_int> sql_int_null;
		typedef Null<sql_int1> sql_int1_null;
		typedef Null<sql_int2> sql_int2_null;
		typedef Null<sql_int3> sql_int3_null;
		typedef Null<sql_int4> sql_int4_null;
		typedef Null<sql_int8> sql_int8_null;
		typedef Null<sql_int_unsigned> sql_int_unsigned_null;
		typedef Null<sql_long> sql_long_null;
		typedef Null<sql_longtext> sql_longtext_null;
		typedef Null<sql_long_varchar> sql_long_varchar_null;
		typedef Null<sql_mediumint> sql_mediumint_null;
		typedef Null<sql_mediumint_unsigned> sql_mediumint_unsigned_null;
		typedef Null<sql_mediumtext> sql_mediumtext_null;
		typedef Null<sql_middleint> sql_middleint_null;
		typedef Null<sql_numeric> sql_numeric_null;
		typedef Null<sql_smallint> sql_smallint_null;
		typedef Null<sql_smallint_unsigned> sql_smallint_unsigned_null;
		typedef Null<sql_text> sql_text_null;
		typedef Null<sql_tinyint> sql_tinyint_null;
		typedef Null<sql_tinyint_unsigned> sql_tinyint_unsigned_null;
		typedef Null<sql_tinytext> sql_tinytext_null;
		typedef Null<sql_varchar> sql_varchar_null;



		// Also do nullable versions of optional sql_* types, where possible
#		if defined(MYSQLPP_SQL_TYPES_H_MYSTRING)
			typedef Null<sql_blob> sql_blob_null;
			typedef Null<sql_longblob> sql_longblob_null;
			typedef Null<sql_mediumblob> sql_mediumblob_null;
			typedef Null<sql_tinyblob> sql_tinyblob_null;
			typedef Null<sql_long_varbinary> sql_long_varbinary_null;
#		endif
#		if defined(MYSQLPP_SQL_TYPES_H_DATETIME)
			typedef Null<sql_date> sql_date_null;
			typedef Null<sql_datetime> sql_datetime_null;
			typedef Null<sql_time> sql_time_null;
			typedef Null<sql_timestamp> sql_timestamp_null;
#		endif
#		if defined(MYSQLPP_SQL_TYPES_H_SET)
			typedef Null<sql_set> sql_set_null;
#		endif
	} // end namespace mysqlpp
#endif
|
|
|
|
|
|

<
>
|
|
|
>
>

>
|

<
<
<
|
>

<
|
|
>
>
>
>
|
>

|
|
|
<
<

>
>
|
|
>

|
>
|

<
>

<
|
|

>
>
>
|
>

<
<
|
>
>
>
>
>
>

<
<
<
<
<
|
|
|
<
>
|
|
|
|
|
<
>
|
|
|
|
|
<
|
<
<
<
<
<
<
>

<
>
>
|
|
|
<
|
>
|
|
|
|
<
<

>
>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<
>

|
>

<
>

>
>

<
<
<
<
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
>
>
>

>
>
>

<
<
|
|
<
|
|
|
|
>
>
>

>
>
>
>
>
>
>

<
<
|
<
<
<
>
>
>
>

|
|
<
|
|
>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
>
>

<
<
|
|
|
|
|
|
|
|
|
|
|
|
<
<
<
<
|
1
2
3
4
5
6
7

8
9
10
11
12
13
14
15
16
17



18
19
20

21
22
23
24
25
26
27
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
56
57
58
59
60
61
62





63
64
65

66
67
68
69
70
71

72
73
74
75
76
77

78






79
80

81
82
83
84
85

86
87
88
89
90
91


92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112

113
114
115
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
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
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211


212
213
214
215
216
217
218
219
220
221
222
223




224
<?xml version="1.0" encoding='UTF-8'?>
<!DOCTYPE sect1 PUBLIC "-//OASIS//DTD DocBook V4.2//EN"
    "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">

<sect1 id="tquery" xreflabel="Template Queries">
  <title>Template Queries</title>


  <para>Another powerful feature of MySQL++ is being able to set up
  template queries. These are kind of like C&#x2019;s
  <function>printf()</function> facility: you give MySQL++ a string
  containing the fixed parts of the query and placeholders for the
  variable parts, and you can later substitute in values into those
  placeholders.</para>

  <para>The following program demonstrates how to use this feature. This
  is <filename>examples/tquery1.cpp</filename>:</para>




  <programlisting><xi:include href="tquery1.txt" parse="text" 
  xmlns:xi="http://www.w3.org/2001/XInclude"/></programlisting>


  <para>The line just before the call to
  <methodname>query.parse()</methodname> sets the template, and the
  parse call puts it into effect. From that point on, you can re-use
  this query by calling any of several Query member functions that
  accept query template parameters. In this example, we&#x2019;re using
  <methodname>Query::execute()</methodname>.</para>

  <para>Let&#x2019;s dig into this feature a little deeper.</para>


  <sect2 id="tquery-setup">
    <title>Setting up Template Queries</title>



    <para>To set up a template query, you simply insert it into the
    Query object, using numbered placeholders wherever you want to be
    able to change the query. Then, you call the parse() function to
    tell the Query object that the query string is a template query,
    and it needs to parse it:</para>

    <programlisting>
query &lt;&lt; "select (%2:field1, %3:field2) from stock where %1:wheref = %0q:what";
query.parse();</programlisting>


    <para>The format of the placeholder is:</para>


    <programlisting>
%###(modifier)(:name)(:)</programlisting>

    <para>Where &#x201C;###&#x201D; is a number up to three digits. It is
    the order of parameters given to a <ulink type="classref"
    url="SQLQueryParms"/> object, starting from 0.</para>

    <para>&#x201C;modifier&#x201D; can be any one of the following:</para>



    <blockquote>
    <informaltable frame="none">
    <tgroup cols="2">
    <colspec colsep="1" rowsep="1"/>
    <tbody>
      <row>
        <entry><emphasis role="bold">%</emphasis></entry>






        <entry>Print an actual &#x201C;%&#x201D;</entry>
      </row>


      <row>
        <entry><emphasis role="bold">""</emphasis></entry>

        <entry>Don&#x2019;t quote or escape no matter what.</entry>
      </row>


      <row>
        <entry><emphasis role="bold">q</emphasis></entry>

        <entry>This will escape the item using the MySQL C API
        function <ulink url="mysql-escape-string" type="mysqlapi"/>
        and add single quotes around it as necessary, depending on

        the type of the value you use.</entry>






      </row>


      <row>
        <entry><emphasis role="bold">Q</emphasis></entry>

        <entry>Quote but don&#x2019;t escape based on the same rules as
        for &#x201C;q&#x201D;. This can save a bit of processing time if

        you know the strings will never need quoting</entry>
      </row>
    </tbody>
    </tgroup>
    </informaltable>
    </blockquote>



    <para>&#x201C;:name&#x201D; is for an optional name which aids in
    filling SQLQueryParms. Name can contain any alpha-numeric characters
    or the underscore. You can have a trailing colon, which will be
    ignored. If you need to represent an actual colon after the name,
    follow the name with two colons. The first one will end the name and
    the second one won&#x2019;t be processed.</para>
  </sect2>


  <sect2 id="tquery-parms">
    <title>Setting the Parameters at Execution Time</title>

    <para>To specify the parameters when you want to execute a query
    simply use <methodname>Query::store(const SQLString &amp;parm0,
    [..., const SQLString &amp;parm11])</methodname>. This type of
    multiple overload also exists for
    <methodname>Query::storein()</methodname>,
    <methodname>Query::use()</methodname> and
    <methodname>Query::execute()</methodname>. &#x201C;parm0&#x201D;
    corresponds to the first parameter, etc. You may specify up to 25

    parameters. For example:</para>

    <programlisting>
StoreQueryResult res = query.store("Dinner Rolls", "item", "item", "price")</programlisting>


    <para>with the template query provided above would produce:</para>

    <programlisting>
select (item, price) from stock where item = "Dinner Rolls"</programlisting>





    <para>The reason we didn&#x2019;t put the template parameters in
    numeric order...</para>

    <programlisting>
select (%0:field1, %1:field2) from stock where %2:wheref = %3q:what</programlisting>

    <para>...will become apparent shortly.</para>
  </sect2>


  <sect2 id="tquery-defaults">
    <title>Default Parameters</title>

    <para>The template query mechanism allows you to set default
    parameter values. You simply assign a value for the parameter to the
    appropriate position in the
    <varname>Query::template_defaults</varname> array. You can refer to
    the parameters either by position or by name:</para>

    <programlisting>
query.template_defaults[1] = "item";
query.template_defaults["wheref"] = "item";</programlisting>



    <para>Both do the same thing.</para>


    <para>This mechanism works much like C++&#x2019;s default function
    parameter mechanism: if you set defaults for the parameters at the
    end of the list, you can call one of
    <classname>Query</classname>&#x2019;s query execution methods without
    passing all of the values. If the query takes four parameters and
    you&#x2019;ve set defaults for the last three, you can execute the
    query using as little as just one explicit parameter.</para>

    <para>Now you can see why we numbered the template query parameters
    the way we did a few sections earlier. We ordered them so that the
    ones less likely to change have higher numbers, so we don&#x2019;t
    always have to pass them. We can just give them defaults and take
    those defaults when applicable. This is most useful when some
    parameters in a template query vary less often than other
    parameters. For example:</para>



    <programlisting>



query.template_defaults["field1"] = "item"; 
query.template_defaults["field2"] = "price"; 
StoreQueryResult res1 = query.store("Hamburger Buns", "item"); 
StoreQueryResult res2 = query.store(1.25, "price"); </programlisting>

    <para>This stores the result of the following queries in
    <varname>res1</varname> and <varname>res2</varname>,

    respectively:</para>

    <programlisting>
select (item, price) from stock where item = "Hamburger Buns"
select (item, price) from stock where price = 1.25</programlisting>

    <para>Default parameters are useful in this example because we have
    two queries to issue, and parameters 2 and 3 remain the same for
    both, while parameters 0 and 1 vary.</para>

    <para>Some have been tempted into using this mechanism as a way to
    set all of the template parameters in a query:</para>

    <programlisting>
query.template_defaults["what"] = "Hamburger Buns";
query.template_defaults["wheref"] = "item";
query.template_defaults["field1"] = "item"; 
query.template_defaults["field2"] = "price"; 
StoreQueryResult res1 = query.store();</programlisting>

    <para>This can work, but it is <emphasis>not designed to</emphasis>.
    In fact, it&#x2019;s known to fail horribly in one common case. You
    will not get sympathy if you complain on the mailing list about it
    not working. If your code doesn&#x2019;t actively reuse at least one
    of the parameters in subsequent queries, you&#x2019;re abusing
    MySQL++, and it is likely to take its revenge on you.</para>
  </sect2>


  <sect2 id="tquery-errors">
    <title>Error Handling</title>

    <para>If for some reason you did not specify all the parameters when
    executing the query and the remaining parameters do not have their
    values set via <varname>Query::template_defaults</varname>, the
    query object will throw a <ulink type="classref"
    url="BadParamCount"/> object. If this happens, you can get an
    explanation of what happened by calling
    <methodname>BadParamCount::what()</methodname>, like so:</para>



    <programlisting>
query.template_defaults["field1"] = "item"; 
query.template_defaults["field2"] = "price"; 
StoreQueryResult res = query.store(1.25); </programlisting>

    <para>This would throw <classname>BadParamCount</classname> because
    the <varname>wheref</varname> is not specified.</para>

    <para>In theory, this exception should never be thrown. If the
    exception is thrown it probably a logic error in your
    program.</para>
  </sect2>




</sect1>

Changes to lib/sqlstream.cpp.






1
2




3
4
5
6

7
8
9
10
11
12
13



14
15
16
17

18


19
20
21
22
23
24

25
26
27
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

56
57
58
59
60
61
62
63

64

65

66








67
68
69
70




71
72
73
74

75
76
77
78
79
80




81
82
83



84
85
86
87
88
89
90
91

92

93
94

95







/***********************************************************************
 sqlstream.cpp - Implements the SQLStream class.





 Copyright (c) 2008 by AboveNet, Inc.  Others may also hold copyrights 
 on code in this file.  See the CREDITS file in the top directory of 
 the distribution for details.


 This file is part of MySQL++.

 MySQL++ is free software; you can redistribute it and/or modify it
 under the terms of the GNU Lesser General Public License as published
 by the Free Software Foundation; either version 2.1 of the License, or
 (at your option) any later version.




 MySQL++ is distributed in the hope that it will be useful, but WITHOUT
 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public

 License for more details.



 You should have received a copy of the GNU Lesser General Public
 License along with MySQL++; if not, write to the Free Software
 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
 USA
***********************************************************************/


#include "sqlstream.h"

#include "dbdriver.h"
#include "connection.h"

#include <string>

namespace mysqlpp {

SQLStream::SQLStream(Connection* c, const char* pstr) :
std::ostringstream(),
conn_(c)
{
	if (pstr != 0) {
		str(pstr);


	}

}







SQLStream::SQLStream(const SQLStream& s) :
std::ostringstream(s.str()),
conn_(s.conn_)
{
}









size_t
SQLStream::escape_string(std::string* ps, const char* original,
		size_t length) const
{

	if (conn_ && *conn_) {
		// Normal case
		return conn_->driver()->escape_string(ps, original, length);
	}
	else {
		// Should only happen in test/test_manip.cpp, since it doesn't
		// want to open a DB connection just to test the manipulators.
		return DBDriver::escape_string_no_conn(ps, original, length);

	}

}











size_t
SQLStream::escape_string(char* escaped, const char* original,
		size_t length) const




{
	if (conn_ && *conn_) {
		// Normal case
		return conn_->driver()->escape_string(escaped, original, length);

	}
	else {
		// Should only happen in test/test_manip.cpp, since it doesn't
		// want to open a DB connection just to test the manipulators.
		return DBDriver::escape_string_no_conn(escaped, original, length);
	}




}





SQLStream&
SQLStream::operator=(const SQLStream& rhs)
{
	conn_ = rhs.conn_;
	str(rhs.str());

	return *this;
}




} // end namespace mysqlpp




>
>
>
>
>
|
<
>
>
>
>

<
<
<
>

<

<
<
|
<
>
>
>

<
<
<
>
|
>
>

|
<
|
<
<
>
|
<

<
|

<
|
<

<
|
<
|
<
<
>
>
|
>
|
|
|
>
>
>
>
>
|
<
<
|
<
>
>
>
>
>
>
|
>
|
<
<
|
|
>
|
|
<
|
<
<
<
<
>
|
>
|
>
|
>
>
>
>
>
>
>
>

<
<
<
>
>
>
>
|
|
|
<
>
|
<
<
<
<
|
>
>
>
>
|
|
|
>
>
>
|
<
|
<
<
|
<
|
>

>

<
>

>
>
1
2
3
4
5
6

7
8
9
10
11



12
13

14


15

16
17
18
19



20
21
22
23
24
25

26


27
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
56
57
58


59
60
61
62
63

64




65
66
67
68
69
70
71
72
73
74
75
76
77
78
79



80
81
82
83
84
85
86

87
88




89
90
91
92
93
94
95
96
97
98
99
100

101


102

103
104
105
106
107

108
109
110
111
Platform Variations
~~~~~~~~~~~~~~~~~~~
    This file only covers details common to all Unix variants
    supported by MySQL++.  For platform-specific details, see the
    file appropriate to your OS:


        README-Cygwin.txt
        README-Linux.txt
        README-Mac-OS-X.txt
        README-Solaris.txt




    There are no special instructions for any other Unix flavors.





Building the Library and Example Programs

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    MySQL++ uses GNU autoconf, so you can build it with the standard
    commands:




    $ ./configure
    $ make
    $ su
    # make install



Configure Options


~~~~~~~~~~~~~~~~~
    The configure script takes several interesting options. Say:



        $ ./configure --help


    to get a list.  Some of the more interesting flags are:



    --prefix:




        If you wish to install mysql++ in a root directory other than
        /usr/local, run configure with --prefix=/some/dir/name

    --with-mysql*:

        If you installed MySQL in an atypical location, the configure
        script will not be able to find the library and header
        files without help.  The simplest way to clue configure into
        where MySQL is installed is with the --with-mysql option.
        Try something like "--with-mysql=/usr/local/mysql", for
        instance.  The configure script will then try to guess which
        subdirectories under the given directory contain the library
        and include files.




        If that doesn't work, it's because the library and header
        files aren't in typical locations under the directory you gave
        for configure to find them.  So, you need to specify them
        separately with --with-mysql-include and --with-mysql-lib
        instead.  As with --with-mysql, configure can often guess
        which subdirectory under the given directory contains the
        needed files, so you don't necessarily have to give the full
        path to these files.
    


    --with-field-limit:

        This lets you increase the maximum field limit for template
        queries and SSQLSes.  By default, both are limited to 25
        fields.  See chapter 8.2 in the user manual for details:






        http://tangentsoft.net/mysql++/doc/html/userman/configuration.html

    --enable-thread-check:

        Builds MySQL++ with threading support, if possible.
        
        This option simply turns on two tests: first, that your
        system uses a compatible threading library; and second,
        that the thread-safe version of the MySQL C API library
        (libmysqlclient_r) is installed and working.  If both of
        these are true, you get a thread-aware version of MySQL++.
        "Thread-aware" means that the library does make an effort to
        prevent problems, but we don't guarantee that all possible
        uses of MySQL++ are thread-safe.




        Note that this is a suggestion, not a command.  If we can't
        figure out the system's threading model or can't find the
        thread-aware build of the C API library, configure won't fail.
        It just reverts to the standard single-thread build.

        See the chapter on threading in the user manual for more
        details and advice on creating thread-safe programs with

        MySQL++.






Building a Static Library
~~~~~~~~~~~~~~~~~~~~~~~~~
    As shipped, MySQL++ only builds a shared library.  It's possible to
    change things so you get a static library instead.

    Before we get to "how," beware that liking statically to MySQL++ has
    legal consequences that may matter to you, due to the library's
    license, the GNU LGPL.  Familiarize yourself with the license, and
    consider getting legal counsel before proceeding.  Also, see the
    MySQL++ FAQ: http://tangentsoft.net/mysql++/#faq  There is more on
    this topic there.




    The necessary changes are all in mysql++.bkl:


        - Change the <dll> tag to <lib>.  (Remember the closing tag!)

        - Remove the <dllname> tag


        - Remove the <so_version> tag

    Then, re-bootstrap the library.  See HACKERS.txt if you need further
    instruction on doing that.

Changes to lib/sqlstream.h.

1



2


3





4
5
6


7

8
9
10
11
12
13
14

15

16
17
18
19
20


21
22
23
24
25


26
27
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
56
57
58





59
60
61
62
63
64
65
66
67

68
69
70

71
72
73
74
75
76

77


78
79
80
81
82
83
84
85
86

87




88
89
90
91
92
93
94
95
96
97
98
99



100
101
102




103
104
105
106
107



108
109
110
111
112
113
114







115






116

117
118
119
120







121
/// \file sqlstream.h



/// \brief Defines a class for building quoted and escaped SQL text.








/***********************************************************************
 Copyright (c) 2008 by AboveNet, Inc.  Others may also hold copyrights
 on code in this file.  See the CREDITS file in the top directory of


 the distribution for details.


 This file is part of MySQL++.

 MySQL++ is free software; you can redistribute it and/or modify it
 under the terms of the GNU Lesser General Public License as published
 by the Free Software Foundation; either version 2.1 of the License, or
 (at your option) any later version.



 MySQL++ is distributed in the hope that it will be useful, but WITHOUT
 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
 License for more details.



 You should have received a copy of the GNU Lesser General Public
 License along with MySQL++; if not, write to the Free Software
 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
 USA
***********************************************************************/



#if !defined(MYSQLPP_SQLSTREAM_H)
#define MYSQLPP_SQLSTREAM_H










#include "common.h"





#include <sstream>


namespace mysqlpp {





#if !defined(DOXYGEN_IGNORE)
// Make Doxygen ignore this
class MYSQLPP_EXPORT Connection;
#endif





/// \brief A class for building SQL-formatted strings.
///
/// See the user manual for more details about these options.

class MYSQLPP_EXPORT SQLStream :
public std::ostringstream






{
public:
	/// \brief Create a new stream object attached to a connection.
	///
	/// \param c connection used for escaping text
	/// \param pstr an optional initial string
	SQLStream(Connection* c, const char* pstr = 0);

	/// \brief Create a new stream object as a copy of another.
	///
	/// This is a traditional copy ctor.
	SQLStream(const SQLStream& s);






	/// \brief Return a SQL-escaped version of a character buffer
	///
	/// \param ps pointer to C++ string to hold escaped version; if
	/// original is 0, also holds the original data to be escaped
	/// \param original if given, pointer to the character buffer to
	/// escape instead of contents of *ps
	/// \param length if both this and original are given, number of
	/// characters to escape instead of ps->length()

	///
	/// \retval number of characters placed in *ps
	///

	/// \see comments for escape_string(char*, const char*, size_t)
	/// and DBDriver::escape_string(std::string*, const char *, size_t)
	/// for further details.
	size_t escape_string(std::string* ps, const char* original = 0,
			size_t length = 0) const;


	/// \brief Return a SQL-escaped version of the given character


	/// buffer
	///
	/// \param escaped character buffer to hold escaped version; must
	/// point to at least (length * 2 + 1) bytes
	/// \param original pointer to the character buffer to escape
	/// \param length number of characters to escape
	///
	/// \retval number of characters placed in escaped
	///

	/// DBDriver provides two versions of this method and 




	/// Query::escape_string() calls the appropriate one based on whether
	/// or not a database connection is available.  If the connection
	/// is available, it can call the DBDriver::escape_string() method.
	/// If there is no database connection available (normally only in
	/// testing), then DBDriver provides a static version of the function 
	/// that doesn't use a database connection.
	///
	/// \see comments for DBDriver::escape_string(char*, const char*, size_t),
	/// DBDriver::escape_string_no_conn(char*, const char*, size_t)
	/// for further details.
	size_t escape_string(char* escaped, const char* original,
			size_t length) const;




	/// \brief Assigns contents of another SQLStream to this one
	SQLStream& operator=(const SQLStream& rhs);





	/// \brief Connection to send queries through
	Connection* conn_;
};





/// \brief Insert raw string into the given stream.
///
/// This is just syntactic sugar for SQLStream::str(void)
inline std::ostream& operator <<(std::ostream& os, SQLStream& s)
{
	return os << s.str();







}









} // end namespace mysqlpp

#endif // !defined(MYSQLPP_SQLSTREAM_H)








|
>
>
>
|
>
>

>
>
>
>
>
|
|
<
>
>
|
>

|

<
<
<
|
>

>
|
<
|
|

>
>
|
<
<
<
<
>
>

<
<
>
>
>
>
>
>
>
>
>

<
>
>

>
>
|

>
|
>
>
>
>

<
<
<
<
>
>
>
>

<
<
<

<
|
>
>
>
>
>
>
|
<
<
<
|
<
<

<
<
<
<
>
>
>
>
>

<
<
<
|
|
|
|
|
>
|
<
<
>
|
<
|
<
<

>
|
>
>
|
|
|
<
|
<
<
<
<
>
|
>
>
>
>
|
|
|
|
<
|
<
<
<
|
|
<
>
>
>
|
|
|
>
>
>
>

<
<
<

>
>
>

<
<
<
<
|
|
>
>
>
>
>
>
>
|
>
>
>
>
>
>

>

<

<
>
>
>
>
>
>
>

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

16
17
18
19
20
21
22



23
24
25
26
27

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
56
57
58
59
60




61
62
63
64
65



66

67
68
69
70
71
72
73
74



75


76




77
78
79
80
81
82



83
84
85
86
87
88
89


90
91

92


93
94
95
96
97
98
99
100

101




102
103
104
105
106
107
108
109
110
111

112



113
114

115
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
144
145
146
147
148
149

150

151
152
153
154
155
156
157
158
Prerequisites
~~~~~~~~~~~~~
    You need to have the MySQL C API development files on your system,
    since MySQL++ is built on top of it.

    The easiest way to get it is to download Connector/C from
    mysql.com.

    If you need the MySQL server on your development system anyway,
    you you can choose to install the development files along with
    the server.  Some versions of the MySQL Server installer for
    Windows have installed the development files by default, while
    others have made it an optional install.



Project Files
~~~~~~~~~~~~~
    The distribution comes with three sets of .sln and .vcproj files
    in the vc2003, vc2005 and vc2008 subdirectories.

    We do this for several reasons:




      1. It lets you build MySQL++ with multiple versions of Visual
         C++ without the build products conflicting.

      2. For Visual C++ 2003, we had to disable the SSQLS feature
         because changes made in MySQL++ 3.0 now cause the compiler

         to crash while building.  See the Breakages chapter in the
         user manual for workarounds if you must still use VC++ 2003.

      3. The VC++ 2008 project files get built for 64-bit output, while
         the other two build 32-bit executables.





         With VC++ 2003, we have no choice about this, since it only
         supports 32-bit targets.



         VC++ 2005 did have experimental 64-bit compilers available,
         but their beta nature was only one reason we chose not to
         use them.  The real reason is that the current MySQL++ build
         system isn't currently set up to make it easy to build both
         32- and 64-bit libraries and executables at the same time
         within the same solution.  Bakefile allows it, but it would
         require forking many of the build rules in mysql++.bkl so
         we can do things like have separate MYSQL_WIN_DIR values
         for each bitness.  (See below for more on this variable.)


         For that same reason, the VC++ 2008 project files are set
         up to build 64-bit libraries and executables *only*.

    It is possible to upgrade these project files to work with newer
    versions of Visual C++, but beware that the upgrade feature tends
    to be problematic.

    When converting the VC++ 2008 project files to VC++ 2012,
    I found that it will screw up the output file names for the
    libraries, so that none of the executables will link properly.
    This problem is detected by the migration process, so that even
    though the tool doesn't know how to fix it itself, you can fix
    it up manually afterward.





    There were also problems in VC++ 2010 when you had converted 32-bit
    VC++ 2008 projects and then were trying to switch them to 64-bit.
    It ended up being simpler in this case to just start over from
    scratch and build your own project files.






Using Nonstandard MySQL Installations
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    The Visual Studio project files that come with MySQL++ have
    everything set up correctly for the common case.  The biggest
    assumption in the settings is that you're building against the
    current stable version of Connector/C, which gets installed here
    at the time of this writing:




        C:\Program Files\MySQL\MySQL Connector C 6.1\







    If you installed a different version, or it's in a different
    directory, or you've installed the development files as part of
    MySQL Server on the same machine, you need to change the project
    files to reference the C API development files in that other
    location.  There are two ways to do this.




    The hard way is to make 16 different changes each to 44 separate
    project files.  If you're a talented Visual Studio driver,
    you can do this in as little as about 5 or 6 steps.  You might
    even get it right the first time.  If you are not so talented,
    you have to make all ~700 changes one at a time, and you almost
    certainly will *not* get it right the first time.



    The somewhat easier way is to open all these files in a text
    editor that lets you make a global search and replace on all

    open files.



    The easy way is to install Bakefile (http://bakefile.org/),
    change the value of the MYSQL_WIN_DIR variable near the top of
    mysql++.bkl in the top level of the MySQL++ source tree, and run
    rebake.bat.  This will rebuild all of the project files for you,
    using the new MySQL path in all the many places it's needed.



Building the Library and Example Programs




~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    You must build both the Debug and Release versions of the library,
    because a release build of your program won't work with a Debug
    version of the MySQL++ DLL.  These DLLs get different names, so
    you can install them in the same directory if needed: mysqlpp_d.dll
    for the Debug version, and mysqlpp.dll for the Release version.

    With the library built, run at least the resetdb and simple1
    examples to ensure that the library is working correctly.
    In addition to the other generic examples, there are a few

    Visual C++ specific examples that you might want to look at in



    examples\vstudio.  See README-examples.txt for further details.


    Once you're sure the library is working correctly, you can run
    the install.hta file at the project root to install the library
    files and headers in a directory of your choosing.
    
    (Aside: You may not have come across the .hta extension before.
    It's for a rarely-used feature of Microsoft's Internet Explorer,
    called HTML Applications.  Know what Adobe AIR is?  Kinda like
    that, only without the compilation into a single binary blob which
    you must install before you can run it.  Just open install.hta
    in a text editor to see how it works.)





Using MySQL++ in Your Own Projects
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    This is covered in the user manual, chapter 9.






Working With Bakefile
~~~~~~~~~~~~~~~~~~~~~
    MySQL++'s top-level Visual Studio project files aren't
    maintained directly.  Instead, we use a tool called Bakefile
    (http://bakefile.org/) to generate them from mysql++.bkl. Since
    there are so many project files in MySQL++, it's often simpler to
    edit this source file and "re-bake" the project files from it than
    to make your changes in Visual Studio.

    To do this, download the native Windows version of Bakefile from the
    web site given above.  Install it, and then put the installation
    directory in your Windows PATH.  Then, open up a command window, cd
    into the MySQL++ directory, and type "rebake".  This will run
    rebake.bat, which rebuilds the Visual Studio project files from
    mysql++.bkl.

    There's more information about using Bakefile in HACKERS.txt.




If You Run Into Problems...
~~~~~~~~~~~~~~~~~~~~~~~~~~~
    Especially if you have linking problems, make sure your project
    settings match the above.  Visual C++ is very picky about things
    like run time library settings.  When in doubt, try running one
    of the example programs.  If it works, the problem is likely in
    your project settings, not in MySQL++.

Changes to lib/ssqls2.cpp.




1


2




3
4



5







6
7





8
9
10


11


12
13




14

15



16


17


18





19

20



21




22





23



24






25






26
27


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
56


57


58


59


60




61












62





63





64











65





66
67
68

69


70




71




72






73


74





75
76


77


78





79



80















81




82
83
84
85

86
87





88

89
90


91







92









/***********************************************************************


 ssqls2.cpp - Implements the SsqlsBase class.





 Copyright (c) 2009 by Educational Technology Resources, Inc.



 Others may also hold copyrights on code in this file.  See the







 CREDITS.txt file in the top directory of the distribution for details.






 This file is part of MySQL++.

 MySQL++ is free software; you can redistribute it and/or modify it


 under the terms of the GNU Lesser General Public License as published


 by the Free Software Foundation; either version 2.1 of the License, or
 (at your option) any later version.






 MySQL++ is distributed in the hope that it will be useful, but WITHOUT



 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or


 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public


 License for more details.







 You should have received a copy of the GNU Lesser General Public



 License along with MySQL++; if not, write to the Free Software




 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301





 USA



***********************************************************************/













#define MYSQLPP_NOT_HEADER
#include "ssqls2.h"








#include "connection.h"




#include "exceptions.h"





#include "query.h"










using namespace std;









// All of the Active Record calls below follow a common pattern, which
// we can only express as a macro.  They just wrap similar calls in
// Query, varying only in minor per-call specific details.
#define QUERY_ACTIVE_RECORD_WRAPPER(action, conn, fs) \
	if (conn) conn_ = conn; \
	if (conn_) { \
		if (conn_->connected()) { \
			if (populated(fs)) return conn_->query().action(*this).execute(); \
			else if (conn_->throw_exceptions()) throw BadQuery( \
					"Cannot " #action " insufficiently populated SSQLS"); \

			else return false; \




		} \





		else if (conn_->throw_exceptions()) throw ConnectionFailed( \





				"Cannot " #action " SSQLS without established connection"); \



		else return false; \


	} \






	else throw ObjectNotInitialized(typeid(*this).name());


namespace mysqlpp {








bool
SsqlsBase::create(Connection* conn) const


{


	(void)conn;


	//TODO define Query::insert(SsqlsBase&)


	//QUERY_ACTIVE_RECORD_WRAPPER(insert, conn, fs_not_autoinc);




	return false;












}











bool











SsqlsBase::load(Connection* conn) const





{
	(void)conn;
	//TODO define Query::select(SsqlsBase&)

	//QUERY_ACTIVE_RECORD_WRAPPER(select, conn, fs_key);


	return false;




}











bool


SsqlsBase::remove(Connection* conn) const





{
	(void)conn;


	//TODO define Query::remove(SsqlsBase&)


	//QUERY_ACTIVE_RECORD_WRAPPER(remove, conn, fs_key);





	return false;



}




















bool
SsqlsBase::save(Connection* conn) const
{
	(void)conn;

	//TODO define Query::update(SsqlsBase&)
	//QUERY_ACTIVE_RECORD_WRAPPER(update, conn, fs_all);





	return false;

}



} // end namespace mysqlpp














>
>
>
|
>
>
|
>
>
>
>

<
>
>
>
|
>
>
>
>
>
>
>
|

>
>
>
>
>
|

|
>
>
|
>
>
|
<
>
>
>
>

>
|
>
>
>
|
>
>
|
>
>
|
>
>
>
>
>

>
|
>
>
>
|
>
>
>
>
|
>
>
>
>
>
|
>
>
>
|
>
>
>
>
>
>

>
>
>
>
>
>
|
|
>
>

>
>
>
>
>
|
>
>
>
>
|
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>

<
>
>
>
>
>
>
>
>

<
<
<
<
<
|
|
|
|
|
>
|
>
>
>
>
|
>
>
>
>
>
|
>
>
>
>
>
|
>
>
>
|
>
>
|
>
>
>
>
>
>
|
>

|
>
>

>
>
>
>
>
|
|
>
>
|
>
>
|
>
>
|
>
>
|
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
|
>
>
>
>
>

>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
|
>
>
>
>
>
|
|
|
>
|
>
>
|
>
>
>
>
|
>
>
>
>

>
>
>
>
>
>
|
>
>
|
>
>
>
>
>
|
|
>
>
|
>
>
|
>
>
>
>
>
|
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

>
>
>
>
|
|
|
|
>
|
<
>
>
>
>
>
|
>
|

>
>
|
>
>
>
>
>
>
>

>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12

13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
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
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
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
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
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
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
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
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
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
<?xml version="1.0" encoding='UTF-8'?>
<!DOCTYPE sect1 PUBLIC "-//OASIS//DTD DocBook V4.2//EN"
    "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">

<sect1 id="incorporating">
  <title>Using MySQL++ in Your Own Project</title>

  <para>Up to now, this manual has only discussed MySQL++
  in conjunction with the example programs that come with the
  library. This chapter covers the steps you need to take to
  incorporate MySQL++ into your own projects.</para>


  <para>The first thing you have to do is include
  <filename>mysql++.h</filename> in each module
  that uses MySQL++. In modules that use <link
  linkend="ssqls">SSQLS v1</link>, you also need to include
  <filename>ssqls.h</filename>.<footnote><para>MySQL++ has many header
  files, but the only one that isn&#x2019;t intertwined with the rest is
  <filename>ssqls.h</filename>. <filename>mysql++.h</filename> brings
  in all of the others in the correct order. Some have tried to speed
  their build times by finding a subset of MySQL++ headers to include,
  but <filename>mysql++.h</filename> already does as much of this as
  is practical. MySQL++&#x2019;s monolithic nature rules out finding
  a true subset of the library headers.</para></footnote></para>

  <para>At this point, your project probably still won&#x2019;t compile,
  and it certainly won&#x2019;t link. The remaining steps are dependent
  on the operating system and tools you are using. The rest of this
  chapter is broken up into several sections, one for each major
  platform type. You can skip over the sections for platforms you
  don&#x2019;t use.</para>


  <sect2 id="inc-vstudio">
    <title>Visual C++</title>

    <sect3 id="inc-vstudio-mfc">
      <title>Using MySQL++ in an MFC Project</title>


      <para>If you don&#x2019;t already have a project set up, open
      Visual Studio, say File | New | Project, then choose Visual C++
      | MFC | MFC Application.  Go through the wizard setting up the
      project as you see fit.</para>

      <para>Once you have your project open, right click on your
      top-level executable in the Solution Explorer, choose Properties,
      and make the following changes.  (Where it doesn&#x2019;t
      specify Debug or Release, make the same change to both
      configurations.)</para>

      <itemizedlist>
        <listitem><para>Append the following to C/C++
        | General | Additional Include Directories:
        <filename>C:\Program Files\MySQL\MySQL Server 5.0\include,
        C:\mysql++\include</filename></para></listitem>

        <listitem><para>Under C/C++ | Code Generation change
        &#x201C;Runtime Library&#x201D; to &#x201C;Multi-threaded
        Debug DLL (/MDd)&#x201D; for the Debug configuration. For
        the Release configuration, make it &#x201C;Multi-threaded DLL
        (/MD)&#x201D;.</para></listitem>

        <listitem>
          <para>Append the following to Linker | General |
          Additional Library Directories for the Debug configuration:
          <filename>C:\Program Files\MySQL\MySQL Server 5.0\lib\debug,
          C:\mysql++\vc\debug</filename></para>

          <para>For the Release configuration, make it the same,
          but change the &#x201C;debug&#x201D; directory names to
          &#x201C;opt&#x201D;.</para>
        </listitem>

        <listitem>
          <para>Under Linker | Input add the following to
          &#x201C;Additional Dependencies&#x201D; for the Debug
          configuration: <filename>libmysql.lib wsock32.lib
          mysqlpp_d.lib</filename></para>

          <para>...and then for the Release configuration:
          <filename>libmysql.lib wsock32.lib
          mysqlpp.lib</filename></para>

          <para>This difference is because MySQL++&#x2019;s Debug
          DLL and import library have a <filename>_d</filename>
          suffix so you can have both in the same directory without
          conflicts.</para>
        </listitem>
      </itemizedlist>

      <para>You may want to study
      <filename>examples\vstudio\mfc\mfc.vcproj</filename>
      to see this in action. Note that some of the paths will
      be different, because it can use relative paths for
      <filename>mysqlpp.dll</filename>.</para>
    </sect3>


    <sect3 id="inc-vstudio-wforms">
      <title>Using MySQL++ in a Windows Forms C++/CLI Project</title>

      <para>Before you start work on getting MySQL++ working with your
      own program, you need to make some changes to the MySQL++ build
      settings. Open <filename>mysqlpp.sln</filename>, then right-click
      on the mysqlpp target and select Properties. Make the following
      changes for both the Debug and Release configurations:</para>

      <itemizedlist>
        <listitem><para>Under Configuration Properties | General,
        change &#x201C;Common Language Runtime support&#x201D; to the
        /clr setting.</para></listitem>

        <listitem><para>Under C/C++ | Code Generation, change
        &#x201C;Enable C++ Exceptions&#x201D; from &#x201C;Yes
        (/EHsc)&#x201D; to &#x201C;Yes With SEH Exceptions
        (/EHa)&#x201D;</para></listitem>
      </itemizedlist>

      <para>If you have already built MySQL++, be sure to perform a
      complete rebuild after changing these options.  The compiler
      will emit several C4835 warnings after making those changes,
      which are harmless when using the DLL with a C++/CLI
      program, but which warn of real problems when using it with
      unmanaged C++.  This is why MySQL++&#x2019;s Windows installer
      (<filename>install.hta</filename>) offers the option to install
      the CLR version into a separate directory; use it if you need
      both managed and unmanaged versions installed!</para>


      <para>For the same reason, you might give some thought about
      where you install <filename>mysqlpp.dll</filename> on your
      end user&#x2019;s machines when distributing your program.
      My recommendation is to install it in the same directory as
      the <filename>.exe</filename> file that uses it, rather than
      installing into a system directory where it could conflict
      with a <filename>mysqlpp.dll</filename> built with different
      settings.</para>






      <para>Once you have MySQL++ built with CLR support, open your
      program&#x2019;s project.  If you don&#x2019;t already have a
      project set up, open Visual Studio, say File | New | Project,
      then choose Visual C++ | CLR | Windows Forms Application.
      Go through the wizard setting up the project as you see
      fit.</para>

      <para>The configuration process isn&#x2019;t much different from
      that for an MFC project, so go through the list above first.
      Then, make the following changes particular to .NET and
      C++/CLI:</para>

      <itemizedlist>
        <listitem><para>Under Configuration Properties | General
        change the setting from /clr:pure to /clr.  (You need mixed
        assembly support to allow a C++/CLI program to use a plain C++
        library like MySQL++.)</para></listitem>

        <listitem><para>For the Linker | Input settings, you
        don&#x2019;t need <filename>wsock32.lib</filename>. The mere
        fact that you&#x2019;re using .NET takes care of that dependency
        for you.</para></listitem>
      </itemizedlist>

      <para>In the MFC instructions above, it said that you need to
      build it using the Multi-threaded DLL version of the C++ Runtime
      Library. That&#x2019;s not strictly true for MFC, but it&#x2019;s
      an absolute requirement for C++/CLI. See the Remarks in <ulink
      url="http://msdn.microsoft.com/en-us/library/k8d11d4s.aspx">the
      MSDN article on the /clr switch</ulink> for details.</para>

      <para>You may want to study
      <filename>examples\vstudio\wforms\wforms.vcproj</filename>
      to see all this in action. Note that some of the
      paths will be different, because it can use relative
      paths for <filename>mysqlpp_d.dll</filename> and
      <filename>mysqlpp.dll</filename>.</para>
    </sect3>
  </sect2>


  <sect2 id="inc-unix">
    <title>Unixy Platforms: Linux, *BSD, OS X, Cygwin, Solaris...</title>

    <para>There are lots of ways to build programs on Unixy
    platforms.  We&#x2019;ll cover just the most generic way
    here, <filename>Makefile</filename>s. We&#x2019;ll use a very
    simple example so it&#x2019;s clear how to translate this
    to more sophisticated build systems such as GNU Autotools or
    Bakefile.</para>

    <para>&#x201C;Hello, world!&#x201D; for MySQL++ might look something
    like this:</para>

    <programlisting><xi:include href="hello.txt" parse="text"
    xmlns:xi="http://www.w3.org/2001/XInclude"/></programlisting>

    <para>Here&#x2019;s a <filename>Makefile</filename> for building
    that program:</para>

    <programlisting><xi:include href="Makefile.hello.posix" parse="text"
    xmlns:xi="http://www.w3.org/2001/XInclude"/></programlisting>

    <para>The <varname>*FLAGS</varname> lines are where all of the
    assumptions about file and path names are laid out. Probably at
    least one of these assumptions isn&#x2019;t true for your system,
    and so will require changing.</para>

    <para>The trickiest line is the <varname>LDLIBS</varname>
    one. MySQL++ programs need to get built against both the MySQL
    and MySQL++ libraries, because MySQL++ is built on top of the
    MySQL C API library<footnote><para>The MySQL C API library
    is most commonly called <filename>libmysqlclient</filename>
    on Unixy systems, though it is also known as <ulink
    url="https://dev.mysql.com/downloads/connector/c/">Connector/C</ulink>.</para></footnote>
    If you&#x2019;re building a threaded program, use
    <filename>-lmysqlclient_r</filename> instead of
    <filename>-lmysqlclient</filename> here. (See <xref
    linkend="threads"/> for more details on building thread-aware
    programs.)</para>

    <para>On some systems, the order of libraries in the
    <varname>LDLIBS</varname> line is important: these linkers collect
    symbols from right to left, so the rightmost library needs to
    be the most generic. In this example, MySQL++ depends on MySQL,
    so the MySQL C API library is rightmost.</para>

    <para>You might need to add more libraries to the
    <varname>LDLIBS</varname> line. <filename>-lnsl</filename>,
    <filename>-lz</filename> and <filename>-lm</filename> are
    common. If you study how MySQL++ itself gets built on your system,
    you can see what it uses, and emulate that.</para>

    <para>You may be wondering why we have used both
    <varname>LDLIBS</varname> and <varname>LDFLAGS</varname>
    here. Some <filename>Makefiles</filename> you have seen probably
    try to collect both types of flags in a single variable. Whether
    that works or not depends on where on the command line those
    flags appear. Since we&rsquo;re depending on the standard
    <filename>make</filename> rules here, we know have to separate
    the <option>-l</option> and <option>-L</option> flags due to the
    place they&rsquo;re inserted into the link command. If you were
    writing your own compilation rules, you could write them in such
    a way that you didn&rsquo;t have to do this.</para>

    <para>Beyond that, we have a pretty vanilla
    <filename>Makefile</filename>, thanks in large part to the fact
    that the default <filename>make</filename> rules are fine for
    such a simple program.</para>
  </sect2>


  <sect2 id="inc-osx">
    <title>OS X</title>

    <sect3 id="inc-osx-makefile">
      <title>Makefiles</title>

      <para>The <link linkend="inc-unix">generic
      <filename>Makefile</filename> instructions above</link>
      cover most of what you need to know about using Makefiles on
      OS X.</para>

      <para>One thing that may trip you up on OS X is that it uses an
      uncommon dynamic linkage system. The easiest way to cope with
      this is to link your executables with the compiler, rather than
      call <filename>ld</filename> directly.</para>

      <para>Another tricky bit on OS X is the concept of Universal
      binaries. See <filename>README-Mac-OS-X.txt</filename> for
      details on building a Universal version of the MySQL++ library,
      if you need one. By default, you only get a version tuned for
      the system type you build it on.</para>
    </sect3>

    <sect3 id="inc-osx-xcode">
      <title>Xcode</title>

      <para>I have no information on how to incorporate MySQL++ in
      an Xcode project. Send a message to the MySQL++ mailing list
      if you can help out here.</para>
    </sect3>
  </sect2>


  <sect2 id="inc-mingw">
    <title>MinGW</title>

    <sect3 id="inc-mingw-makefile">
      <title>Makefiles</title>

      <para>The <link linkend="inc-unix">generic
      <filename>Makefile</filename> instructions above</link> apply
      to MinGW&#x2019;s version of GNU <filename>make</filename> as
      well. You will have some differences due to the platform, so
      here&#x2019;s the adjusted <filename>Makefile</filename>:</para>

      <programlisting><xi:include
      href="Makefile.hello.mingw" parse="text"
      xmlns:xi="http://www.w3.org/2001/XInclude"/></programlisting>

      <para>Note that I&#x2019;ve used <command>del</command>
      instead of <command>rm</command> in the clean target. In
      the past, at least, MinGW <filename>make</filename>
      had some funny rules about whether commands in target
      rules would get run with <filename>sh.exe</filename>
      or with <filename>cmd.exe</filename>. I can&rsquo;t
      currently get my installation of MinGW to do anything
      but use <filename>sh.exe</filename> by default, but that
      may be because I have Cygwin installed, which provides
      <filename>sh.exe</filename>.  This explains the first
      line in the file, which overrides the default shell with
      <filename>cmd.exe</filename>, purely to get consistent
      behavior across platforms. If you knew all your platforms
      would have a better shell, you&rsquo;d probably want to use
      that instead.</para>

      <para>Note the use of forward slashes in the path to the MySQL
      Connector/C development files. GNU <filename>make</filename>
      uses the backslash as an escape character, so you&#x2019;d
      have to double them if you&#x2019;re unwilling to use forward
      slashes.</para>
    </sect3>

    <sect3 id="inc-mingw-ide">
      <title>Third-Party MinGW IDEs (Dev-C++, Code::Blocks...)</title>


      <para>I have no information on how to do this. We&#x2019;ve
      received reports on the mailing list from people that have made
      it work, but no specifics on what all needs to be done. The
      <filename>Makefile</filename> discussion above should give you
      some hints.</para>
    </sect3>
  </sect2>


  <sect2 id="inc-eclipse">
    <title>Eclipse</title>

    <para>As far as I can tell, the simplest way to build a C++ project
    with Eclipse is to set up a <filename>Makefile</filename> for it
    as described <link linkend="inc-unix">above</link>, then add an
    external run configuration for your local <filename>make</filename>
    tool. Get the project building from the command line with
    <filename>make</filename>, then go to Run | External Tools | Open
    External Tools Dialog and add a new launch configuration.</para>

    <para>For example, on my OS X system I use
    <filename>/usr/bin/gnumake</filename> for the program location
    and pick the project root with the Browse Workspace button to
    set the working directory.</para>
  </sect2>
</sect1>

Changes to lib/ssqls2.h.

1
2

3
4
5



6
7
8
9
10
11
12
/// \file ssqls2.h
/// \brief Declares the SsqlsBase class


/***********************************************************************
 Copyright (c) 2009 by Educational Technology Resources, Inc.



 Others may also hold copyrights on code in this file.  See the
 CREDITS.txt file in the top directory of the distribution for details.

 This file is part of MySQL++.

 MySQL++ is free software; you can redistribute it and/or modify it
 under the terms of the GNU Lesser General Public License as published
|
|
>

<
|
>
>
>







1
2
3
4

5
6
7
8
9
10
11
12
13
14
15
/***********************************************************************
 cmdline.cpp - Command line parsing stuff used by the example and
    utility programs.  Not intended for end-user use!


 Copyright (c) 2007-2009 by Educational Technology Resources,
 Inc.  getopt() and its associated globals are the public domain
 implementation made available at the 1985 UNIFORUM conference in
 Dallas, Texas; the code is untouched except for style tweaks.
 Others may also hold copyrights on code in this file.  See the
 CREDITS.txt file in the top directory of the distribution for details.

 This file is part of MySQL++.

 MySQL++ is free software; you can redistribute it and/or modify it
 under the terms of the GNU Lesser General Public License as published
20
21
22
23
24
25
26
27
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
56


57
58
59
60
61
62

63


64

65


66
67
68
69
70

71
72

73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88












89
90
91
92
93
94
95
96
97

98








99

100
101
102

103
104
105
106
107
108
109
110
111
112
113
114



115
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
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
191
192
193
194
195
196
197
198
199



200
201
202
203
204
205
206
207
208
209


210
211
212
213
214
215
216
217



218




219
220
221
222


223
224
225
226
227
228
229

230
231


232
233

234


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
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
311

 You should have received a copy of the GNU Lesser General Public
 License along with MySQL++; if not, write to the Free Software
 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
 USA
***********************************************************************/

#if !defined(MYSQLPP_SSQLS2_H)
#define MYSQLPP_SSQLS2_H

#include "common.h"

#include <iostream>

namespace mysqlpp {



#if !defined(DOXYGEN_IGNORE)
// Make Doxygen ignore this
class MYSQLPP_EXPORT Connection;
class MYSQLPP_EXPORT Row;
#endif

/// \brief Base class for all SSQLSv2 classes
///

/// Classes generated by ssqlsxlat derive from this class.  It is not
/// directly instantiable.  It exists only to hold the common interface
/// to all SSQLSv2 classes.
class MYSQLPP_EXPORT SsqlsBase







{
public:
	/// \brief Supported field subsets
	enum FieldSubset {
		fs_all,			///< all fields
		fs_key,			///< fields with "is key" attribute
		fs_set,			///< fields that have been given a value
		fs_not_autoinc	///< fields without "is autoinc" attribute
	};



	/// \brief Create table in database matching subclass schema
	///
	/// \param conn If given, use this connection instead of the one we
	/// may have gotten earlier; saves value for future use.
	///

	/// \return true if table was successfully created; on failure,


	/// only returns false if conn->throw_exceptions() is false.

	virtual bool create_table(Connection* conn = 0) const = 0;



	/// \brief Create record in database from all fields in object
	/// except for any marked as auto-increment.
	///
	/// \param conn If given, use this connection instead of the one we

	/// may have gotten earlier; saves value for future use.
	///

	/// \return true if new record was successfully created; on failure,
	/// only returns false if conn->throw_exceptions() is false.
	bool create(Connection* conn = 0) const;

	/// \brief Puts stream insertion operator into "equal list" mode
	///
	/// Typical usage:
	///
	/// \code cout << foo.equal_list() << endl;
	///
	/// \see operator<<(std::ostream&, const SsqlsBase&)
	const SsqlsBase& equal_list() const
	{
		output_mode_ = om_equal_list;
		return *this;
	}













	/// \brief Insert SSQLS's names and values into a stream.
	///
	/// An "equal list" is a set of name/value pairs in SQL assignment
	/// form, suitable for building INSERT queries and such.
	///
	/// \param os output stream to insert equal list into
	/// \param fs with default value, only the fields that have been
	/// given values are included in the output

	virtual std::ostream& equal_list(std::ostream& os,








			FieldSubset fs = fs_set) const = 0;


	/// \brief Set a per-instance SQL table name
	///

	/// This causes table() to return the passed value instead of the
	/// static per-class value it normally returns.  This is useful if
	/// you're using a single SSQLS definition for multiple tables that
	/// happen to share a common schema or schema subset.
	void instance_table(const char* name)
			{ instance_table_name_ = name; }

	/// \brief Retrieve record from the database matching our key field(s)
	///
	/// \param conn If given, use this connection instead of the one we
	/// may have gotten earlier; saves value for future use.
	///



	/// \return true if record was successfully retrieved; on failure,
	/// only returns false if conn->throw_exceptions() is false.
	bool load(Connection* conn = 0) const;







	/// \brief Puts stream insertion operator into "name list" mode
	///



	/// Typical usage:
	///
	/// \code cout << foo.name_list() << endl;
	///
	/// \see operator<<(std::ostream&, const SsqlsBase&)
	const SsqlsBase& name_list() const
	{
		output_mode_ = om_name_list;
		return *this;
	}






	/// \brief Insert the SSQLS's field names into a stream
	///
	/// A "name list" is a comma-separated list of SSQLS field names
	///
	/// \param os output stream to insert name list into
	/// \param fs with default value, only the names of fields that have
	/// been given values are included in the output
	virtual std::ostream& name_list(std::ostream& os,
			FieldSubset fs = fs_set) const = 0;

	/// \brief Returns truthy value if object's fields have been fully

	/// populated.
	///



	/// Test the Row, result or Query class you used to assign the
	/// value to distinguish a successful subset population from
	/// a complete failure to populate the object.  Because of this
	/// ambiguity, this operator is only useful for checking that an
	/// expected full population did in fact fully populate the object.
	/// This can help you to detect schema drift.

	operator const void*() const { return populated() ? this : 0; }


	/// \brief Returns true if the object has been populated
	///
	/// \param fs field subset to check, defaulting to "all fields"
	///

	/// This can give a different result than testing the object in
	/// bool context if you pass something other than fs_all.

	virtual bool populated(FieldSubset fs = fs_all) const = 0;

	/// \brief Delete record matching our key field(s) from the database
	///
	/// \param conn If given, use this connection instead of the one we
	/// may have gotten earlier; saves value for future use.
	///


	/// \return true if record was successfully removed; on failure,

	/// only returns false if conn->throw_exceptions() is false.
	bool remove(Connection* conn = 0) const;



	/// \brief Update record in database matching our key fields, or
	/// insert it if there is no such record.

	///
	/// \param conn If given, use this connection instead of the one we
	/// may have gotten earlier; saves value for future use.
	///
	/// \return true if record was successfully saved; on failure,
	/// only returns false if conn->throw_exceptions() is false.
	bool save(Connection* conn = 0) const;








	/// \brief Get the object's SQL table name
	///
	/// \r return the value set by instance_table(), if you called it,
	/// or a static per-class value otherwise










	const char* table() const { return instance_table_name_; }

	/// \brief Puts stream insertion operator into "value list" mode
	///
	/// Typical usage:

	///
	/// \code cout << foo.value_list() << endl;
	///
	/// \see operator<<(std::ostream&, const SsqlsBase&)
	const SsqlsBase& value_list() const
	{
		output_mode_ = om_value_list;
		return *this;
	}

	/// \brief Insert SSQLS's values into a stream.



	///
	/// A "value list" is a comma-separated list of SSQLS field values.
	/// Whether the values are quoted and/or escaped depends on the
	/// stream type passed for os.
	///
	/// \param os output stream to insert value list into
	/// \param fs with default value, only the fields that have been
	/// given values are included in the output
	virtual std::ostream& value_list(std::ostream& os,
			FieldSubset fs = fs_set) const = 0;



protected:
	/// \brief Default constructor
	///
	/// \param conn pointer to connection we should use for Active
	/// Record methods' queries, if no connection is passed for that
	/// particular call.
	SsqlsBase(Connection* conn = 0) :



	output_mode_(om_value_list),




	conn_(conn),
	instance_table_name_(0)
	{
	}



	/// \brief Full initialization constructor
	///
	/// \param row data to use in initializing SSQLS fields
	/// \param conn pointer to connection we should use for Active
	/// Record methods' queries, if no connection is passed for that
	/// particular call.

	/// \todo do something with row parameter
	SsqlsBase(const Row& row, Connection* conn = 0) :


	output_mode_(om_value_list),
	conn_(conn),

	instance_table_name_(0)


	{
#if !defined(_MSC_VER)
		// Unused parameter warning squisher.  VC++ can't cope without
		// including row.h, which we don't want to do just to squish a
		// warning.  It doesn't warn anyway, so...
		(void)row;	
#endif
	}










	/// \brief Destructor



	virtual ~SsqlsBase() { }



	/// \brief Flag controlling the behavior of operator<<()
	mutable enum {
		om_equal_list,
		om_name_list,
		om_value_list
	} output_mode_;





	/// \brief Connection object we were initialized from, if any



	///
	/// This just provides a default for the Active Record methods

	/// above that take Connection*.

	mutable Connection* conn_;



private:
	/// \brief Table name override for this particular object
	const char* instance_table_name_;

	friend std::ostream& operator <<(std::ostream&, const SsqlsBase&);
};








/// \brief Put contents of an SSQLSv2 derivative into a \c std::ostream
///

/// If you use this operator directly, you get a comma-separated list of



/// field values in the ostream.  Whether those values are quoted and/or
/// escaped depends on the ostream type.
/// 
/// It is also useful to use this operator indirectly, via
/// SsqlsBase::equal_list() or SsqlsBase::name_list().  (There is also a
/// SsqlsBase::value_list(), but it's just an alias for calling this operator
/// directly.)  These methods set a flag on the object that causes this
/// operator to insert an equals list (e.g. "name1 = value1, name2 =
/// value2...") or a name list into the stream.  The flag is immediately
/// reset to give value lists again on completion of the insert operation.
/// For example:
///
/// \code
/// stock s = ...;	// initialize an SSQLSv2 object of 'stock' class
/// cout << "Set field names: " << s.name_list() << endl;
/// \endcode
///
/// The \c s.name_list() call sets the output mode to "names", then passes
/// \c cout and \c *this to this operator, which then calls the version
/// of s.name_list() taking a stream reference, which is overridden in
/// the leaf class to know how to insert the names of all fields set on
/// the \c s object.
///
/// \param os IOstream to insert object contents into
/// \param sb object to insert into the stream
std::ostream& operator <<(std::ostream& os, const SsqlsBase& sb)
{
	switch (sb.output_mode_) {
		case SsqlsBase::om_equal_list: sb.equal_list(os); break;
		case SsqlsBase::om_name_list:  sb.name_list(os);  break;
		case SsqlsBase::om_value_list: sb.value_list(os); break;
	}









	sb.output_mode_ = SsqlsBase::om_value_list;






	return os;



}

} // end namespace mysqlpp

#endif // !defined(MYSQLPP_SSQLS2_H)







<
|
<
|



|
>
>

|
<
<
|
|

|
<
>
|
|
<
|
>
>
>
>
>
>
>
|
|
|
|
|
|
|
|
<
>
>
|
<
<
<
<
<
>
|
>
>
|
>
|
>
>

|
|
<
|
>
|
<
>
|
<
|
|
<
<
<
<
<
<
<
<
|
<
|
|
>
>
>
>
>
>
>
>
>
>
>
>
|
<
<
<
<
<
|
|
<
>
|
>
>
>
>
>
>
>
>
|
>
|
<
|
>
|
|
|
|
|
|

|
|
|
|
<
>
>
>
|
|
|
>
>
>
|
>
>
>
|
|
>
>
>
|
<
<
<
|
|
|
<
|
|
>
>
>
>
>

|
<
<
<
<
<
<
<
|
|
|
>
|
|
>
>
>
|
|
|
<
<
<
>
|
>

|
|
|
|
>
|
|
>
|
|
<
<
|
|
<
>
>
|
>
|
|
>
>

|
|
>
|
|
<
|
|
|
|
>
>
>
>
>
>
>
|
<
<
<
<
>
>
>
>
>
>
>
>
>
>
|
|
<
<
<
>
<
<
<
<
<
|
<
|
|

|
>
>
>
|
<
<
<
<
<
<
<
<
<
>
>
|
|
<
<
|
|
|
|
>
>
>
|
>
>
>
>
|
<
<
|
>
>

|
|
|
|
|
|
>
|
|
>
>
|
|
>
|
>
>
|
|
<
<
<
<
|
<
>
>
>
>
>
>
>
>
>
|
<
>
>
>
|
>
>

<
|
<
|
<
|
>

>
>
>
|
>
>
>
|
<
>
|
>
|
>
>
|
<
<
<
|
<
<
>

>
>
>
>
>
|
<
<
>
|
>
>
>
|
|
<
<
<
<
<
<
<
|
|
<
<
|
<
<
<
<
<
<
<
<
<
<
<
<
|
<
<
<
<
<
>
>
|
>
>
>
>
>
>
|
|
>
>
>
>
>
|
>
>
>


|
|
<
23
24
25
26
27
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
56
57
58
59
60
61
62

63
64
65





66
67
68
69
70
71
72
73
74
75
76
77

78
79
80

81
82

83
84








85

86
87
88
89
90
91
92
93
94
95
96
97
98
99
100





101
102

103
104
105
106
107
108
109
110
111
112
113
114
115

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
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
191
192
193
194
195
196
197
198
199
200
201

202
203
204
205
206
207
208
209
210
211
212
213




214
215
216
217
218
219
220
221
222
223
224
225



226





227

228
229
230
231
232
233
234
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
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
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
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357


 You should have received a copy of the GNU Lesser General Public
 License along with MySQL++; if not, write to the Free Software
 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
 USA
***********************************************************************/


#define MYSQLPP_NOT_HEADER

#include "cmdline.h"

#include <iostream>

#include <stdio.h>
#include <stdlib.h>
#include <string.h>




//// getopt ////////////////////////////////////////////////////////////
// Bring in system getopt(), or define our own.

#if defined(HAVE_POSIX_GETOPT)

#	include <unistd.h>
#elif defined(HAVE_LIBIBERTY_GETOPT)
#	include <libiberty.h>

#else
	// Need to define our own getopt() on this system
	extern "C" {
		// Using C linkage to avoid potential conflicts with system
		// getopt(), if autoconf test fails to find it.
		static const char* optarg;
		static int optind = 1;
		static int getopt(int argc, char* const argv[], const char* opts)
		{
			static int optopt;
			static int sp = 1;
			register int c;
			register const char *cp;

			if (sp == 1) {
				/* If all args are processed, finish */

				if (optind >= argc) {
					return EOF;
				}





				if (argv[optind][0] != '-' || argv[optind][1] == '\0') {
					return EOF;
				}
			}
			else if (!strcmp(argv[optind], "--")) {
				/* No more goptions to be processed after this one */
				optind++;
				return EOF;
			}

			optopt = c = argv[optind][sp];


			/* Check for invalid goption */
			if (c == ':' || (cp = strchr(opts, c)) == 0) {
				fprintf(stderr, "%s: illegal option -- %c\n", argv[0], c);

				if (argv[optind][++sp] == '\0') {
					optind++;

					sp = 1;
				}










				return '?';
			}

			/* Does this goption require an argument? */
			if (*++cp == ':') {
				/* If so, get argument; if none provided output error */
				if (argv[optind][sp + 1] != '\0') {
					optarg = &argv[optind++][sp + 1];
				}
				else if (++optind >= argc) {
					fprintf(stderr,
							"%s: option requires an argument -- %c\n", argv[0], c);
					sp = 1;
					return '?';
				}





				else {
					optarg = argv[optind++];

				}
				sp = 1;
			}
			else {
				if (argv[optind][++sp] == '\0') {
					sp = 1;
					optind++;
				}
				optarg = 0;
			}

			return c;
		}

	} // end extern "C" 
#endif // didn't find either POSIX or libiberty getopt()


////////////////////////////////////////////////////////////////////////
// Generic MySQL++-specific command line parsing mechanism

namespace mysqlpp {

//// CommandLineBase::finish_parse /////////////////////////////////////
// Called by subclass when it's finished parsing the command line.  It
// does nothing if we're not still in a "successful" state.


void
CommandLineBase::finish_parse()
{
	if (successful_) {
		const int nextras = argc_ - option_index();
		if (nextras > 0) {
			extra_args_.resize(nextras);
			for (int i = 0; i < nextras; ++i) {
				extra_args_[i] = argv_[option_index() + i];
			}
		}
	}
}


//// CommandLineBase::option_argument //////////////////////////////////
// Accessor for optarg, so caller doesn't have to know about this
// getopt() style interface.  Particualy helpful on non-POSIX systems.




const char*
CommandLineBase::option_argument() const
{

	return optarg;
}


//// CommandLineBase::option_index /////////////////////////////////////
// Accessor for optind, so caller doesn't have to know about this
// getopt() style interface.  Particuarly helpful on non-POSIX systems.

int







CommandLineBase::option_index() const
{
	return optind;
}


//// CommandLineBase::parse_next ///////////////////////////////////////
// Wrapper around getopt(), using the stuff passed to our ctor to
// construct its argument list.

int
CommandLineBase::parse_next() const



{
	return getopt(argc_, argv_, opts_);
}


//// CommandLineBase::parse_error //////////////////////////////////////
// Called by subclasses when they encounter an error in parsing.  We
// wrap up several details of handling that error: display the
// message on stderr, call the subclass's print_usage() method, and
// marks the object as no longer successful.

void
CommandLineBase::parse_error(const char* message)
{


	if (message) {
		std::cerr << message << '\n';

	}
	print_usage();
	successful_ = false;
}


////////////////////////////////////////////////////////////////////////
// Command line parser for MySQL++ examples.

namespace examples {

const char* db_name = "mysql_cpp_data";



//// examples::CommandLine ctor ////////////////////////////////////////

CommandLine::CommandLine(int argc, char* const argv[],
		const char* user, const char* pass, const char* usage_extra) :
CommandLineBase(argc, argv, "hm:p:s:u:D?"),
dtest_mode_(false),
run_mode_(0),
server_(0),
user_(user && *user ? user : 0),
pass_(pass && *pass ? pass : ""),
usage_extra_(usage_extra)
{




	int ch;
	while (successful() && ((ch = parse_next()) != EOF)) {
		switch (ch) {
			case 'm': run_mode_ = atoi(option_argument()); break;
			case 'p': pass_ = option_argument();           break;
			case 's': server_ = option_argument();         break;
			case 'u': user_ = option_argument();           break;
			case 'D': dtest_mode_ = true;                  break;
			default:
				parse_error();
				return;
		}



	}







	finish_parse();
}


//// examples::CommandLine::print_usage ////////////////////////////////
// Show a generic usage message suitable for ../examples/*.cpp  The
// parameters specialize the message to a minor degree.










void
CommandLine::print_usage(const char* extra) const
{
	std::cout << "usage: " << program_name() <<


			" [-s server_addr] [-u user] [-p password] " <<
			(extra ? extra : "") << std::endl;
	std::cout << std::endl;
	std::cout << "    If no options are given, connects to database "
			"server on localhost" << std::endl;
	std::cout << "    using your user name and no password." << std::endl;
	if (extra && (strlen(extra) > 0)) {
		std::cout << std::endl;
		std::cout << "    The extra parameter " << extra <<
				" is required, regardless of which" << std::endl;
		std::cout << "    other arguments you pass." << std::endl;
	}
	std::cout << std::endl;


}

} // end namespace mysqlpp::examples


////////////////////////////////////////////////////////////////////////
// Command line parser for MySQL++'s ssqlsxlat tool.

namespace ssqlsxlat {

//// ssqlsxlat::CommandLine ctor ////////////////////////////////////////

CommandLine::CommandLine(int argc, char* const argv[]) :
CommandLineBase(argc, argv, "hi:o:p:s:t:u:1:?"),
input_(0),
output_(0),
pass_(""),
server_(0),
user_(0),
input_source_(ss_unknown),
output_sink_(ss_unknown)
{
	// Parse the command line




	int ch;

	while (successful() && ((ch = parse_next()) != EOF)) {
		switch (ch) {
			case 'i':
			case 't':
			case '1':
				if (input_) {
					std::cerr << "Warning: overriding previous input "
							"source!  Only last -i, -t or -1 is "
							"effective.\n";
				}

				input_ = option_argument();
				input_source_ =
						(ch == '1' ? ss_ssqls1 :
						 ch == 'i' ? ss_ssqls2 :
						             ss_table);
				break;


			case 'o':

				output_ = option_argument();

				output_sink_ = ss_ssqls2;
				break;

			case 'p':
				pass_ = option_argument();
				break;

			case 's':
				server_ = option_argument();
				break;


			case 'u':
				user_ = option_argument();
				break;

			default:
				parse_error();
		}



	}


	finish_parse();

	// Figure out whether command line makes sense, and if not, tell
	// user about it.
	if (successful()) {
		if (input_source_ == ss_unknown) {
			parse_error("No input source given!  Need -i, -t or -1.");
		}


		else if ((input_source_ != ss_ssqls2) && !output_) {
			parse_error("Need -o if you give -t or -1!");
		}
	}
}









//// ssqlsxlat::CommandLine::print_usage ////////////////////////////////
// Show a generic usage message suitable for ../ssqlsxlat/*.cpp  The


// parameters specialize the message to a minor degree.


















void
CommandLine::print_usage() const
{
	std::cerr << "usage: " << program_name() <<
        	" [ -i input.ssqls ] [ -1 input-ssqlsv1.cpp ]\n"
			"        [ -u user ] [ -p password ] [ -s server ] [ -t table ]\n"
			"        [ -o parsedump.ssqls ]\n";
	std::cerr << std::endl;
	std::cerr <<
			"        -i: parse SSQLSv2 DSL, generating C++ output at minimum\n"
			"        -o: write out .ssqls file containing info found by\n"
			"            processing -i, -t or -1\n"
			"  -u,p,s,t: log into server with given creds, get schema details\n"
			"            for a table, and generate output as if parsed from\n"
			"            SSQLSv2 DSL; requires -o\n"
			"        -1: find SSQLSv1 declarations in C++ code, and try to\n"
			"            interpret as equivalent SSQLSv2; requires -o\n"
			"      -?,h: write out .ssqls file containing info found by\n"
			"            processing -i, -t or -1\n";
	std::cerr << std::endl;
}

} // end namespace mysqlpp::ssqlsxlat
} // end namespace mysqlpp

Changes to lib/stream2string.h.

1
2
3
4
5



6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33

34
35







36










37






38



























































39
40



41





42


43



44








45
46
47






















48














49



















50
51


/// \file stream2string.h
/// \brief Declares an adapter that converts something that can be
/// inserted into a C++ stream into a std::string type.

/***********************************************************************



 Copyright (c) 1998 by Kevin Atkinson, (c) 1999-2001 by MySQL AB, and
 (c) 2004-2007 by Educational Technology Resources, Inc.  Others may
 also hold copyrights on code in this file.  See the CREDITS.txt file
 in the top directory of the distribution for details.

 This file is part of MySQL++.

 MySQL++ is free software; you can redistribute it and/or modify it
 under the terms of the GNU Lesser General Public License as published
 by the Free Software Foundation; either version 2.1 of the License, or
 (at your option) any later version.

 MySQL++ is distributed in the hope that it will be useful, but WITHOUT
 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
 License for more details.

 You should have received a copy of the GNU Lesser General Public
 License along with MySQL++; if not, write to the Free Software
 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
 USA
***********************************************************************/

#if !defined(MYSQLPP_STREAM2STRING_H)
#define MYSQLPP_STREAM2STRING_H

#include <sstream>
#include <string>


namespace mysqlpp {


















/// \brief Converts anything you can insert into a C++ stream to a






/// \c std::string via \c std::ostringstream.




























































template <class T>



std::string stream2string(const T& object)





{


	std::ostringstream str;



	str << object;








	return str.str();
}























} // end namespace mysqlpp


































#endif // !defined(MYSQLPP_STREAM2STRING_H)



<
<
<
<

>
>
>
|
|
|
|



















|
|

|
|
>

|
>
>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
|
>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
|
>
>
>
|
>
>
>
>
>
|
>
>
|
>
>
>
|
>
>
>
>
>
>
>
>
|
|

>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|

>
>




1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
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
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
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
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
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211




/***********************************************************************
 cpool.cpp - ConnectionPool example.  Works with both Windows native
	threads and POSIX threads.  Shows how to create and use a concrete
	ConnectionPool derivative.

 Copyright (c) 2008 by Educational Technology Resources, Inc.
 Others may also hold copyrights on code in this file.  See the
 CREDITS file in the top directory of the distribution for details.

 This file is part of MySQL++.

 MySQL++ is free software; you can redistribute it and/or modify it
 under the terms of the GNU Lesser General Public License as published
 by the Free Software Foundation; either version 2.1 of the License, or
 (at your option) any later version.

 MySQL++ is distributed in the hope that it will be useful, but WITHOUT
 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
 License for more details.

 You should have received a copy of the GNU Lesser General Public
 License along with MySQL++; if not, write to the Free Software
 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
 USA
***********************************************************************/

#include "cmdline.h"
#include "threads.h"

#include <iostream>

using namespace std;


// Define a concrete ConnectionPool derivative.  Takes connection
// parameters as inputs to its ctor, which it uses to create the
// connections we're called upon to make.  Note that we also declare
// a global pointer to an object of this type, which we create soon
// after startup; this should be a common usage pattern, as what use
// are multiple pools?
class SimpleConnectionPool : public mysqlpp::ConnectionPool
{
public:
	// The object's only constructor
	SimpleConnectionPool(const char* db, const char* server,
			const char* user, const char* password) :
	db_(db ? db : ""),
	server_(server ? server : ""),
	user_(user ? user : ""),
	password_(password ? password : "")
	{
	}

	// The destructor.  We _must_ call ConnectionPool::clear() here,
	// because our superclass can't do it for us.
	~SimpleConnectionPool()
	{
		clear();
	}

protected:
	// Superclass overrides
	mysqlpp::Connection* create()
	{
		// Create connection using the parameters we were passed upon
		// creation.  This could be something much more complex, but for
		// the purposes of the example, this suffices.
		cout.put('C'); cout.flush(); // indicate connection creation
		return new mysqlpp::Connection(
				db_.empty() ? 0 : db_.c_str(),
				server_.empty() ? 0 : server_.c_str(),
				user_.empty() ? 0 : user_.c_str(),
				password_.empty() ? "" : password_.c_str());
	}

	void destroy(mysqlpp::Connection* cp)
	{
		// Our superclass can't know how we created the Connection, so
		// it delegates destruction to us, to be safe.
		cout.put('D'); cout.flush(); // indicate connection destruction
		delete cp;
	}

	unsigned int max_idle_time()
	{
		// Set our idle time at an example-friendly 3 seconds.  A real
		// pool would return some fraction of the server's connection
		// idle timeout instead.
		return 3;
	}

private:
	// Our connection parameters
	std::string db_, server_, user_, password_;
};
SimpleConnectionPool* poolptr = 0;


#if defined(HAVE_THREADS)
static thread_return_t CALLBACK_SPECIFIER
worker_thread(thread_arg_t running_flag)
{
	// Pull data from the sample table a bunch of times, releasing the
	// connection we use each time.
	for (size_t i = 0; i < 6; ++i) {
		// Go get a free connection from the pool, or create a new one
		// if there are no free conns yet.
		mysqlpp::Connection* cp = poolptr->grab();
		if (!cp) {
			cerr << "Failed to get a connection from the pool!" << endl;
			break;
		}

		// Pull a copy of the sample stock table and print a dot for
		// each row in the result set.
		mysqlpp::Query query(cp->query("select * from stock"));
		mysqlpp::StoreQueryResult res = query.store();
		for (size_t j = 0; j < res.num_rows(); ++j) {
			cout.put('.');
		}

		// Immediately release the connection once we're done using it.
		// If we don't, the pool can't detect idle connections reliably.
		poolptr->release(cp);

		// Delay 1-4 seconds before doing it again.  Because this can
		// delay longer than the idle timeout, we'll occasionally force
		// the creation of a new connection on the next loop.
		sleep(rand() % 4 + 1);	
	}

	// Tell main() that this thread is no longer running
	*reinterpret_cast<bool*>(running_flag) = false;
	
	return 0;
}
#endif


int
main(int argc, char *argv[])
{
#if defined(HAVE_THREADS)
	// Get database access parameters from command line
    const char* db = 0, *server = 0, *user = 0, *pass = "";
	if (!parse_command_line(argc, argv, &db, &server, &user, &pass)) {
		return 1;
	}

	// Create the pool and grab a connection.  We do it partly to test
	// that the parameters are good before we start doing real work, and
	// partly because we need a Connection object to call thread_aware()
	// on to check that it's okay to start doing that real work.  This
	// latter check should never fail on Windows, but will fail on most
	// other systems unless you take positive steps to build with thread
	// awareness turned on.  See README-*.txt for your platform.
	poolptr = new SimpleConnectionPool(db, server, user, pass);
	try {
		mysqlpp::Connection* cp = poolptr->grab();
		if (!cp->thread_aware()) {
			cerr << "MySQL++ wasn't built with thread awareness!  " <<
					argv[0] << " can't run without it." << endl;
			return 1;
		}
		poolptr->release(cp);
	}
	catch (mysqlpp::Exception& e) {
		cerr << "Failed to set up initial pooled connection: " <<
				e.what() << endl;
		return 1;
	}

	// Setup complete.  Now let's spin some threads...
	cout << endl << "Pool created and working correctly.  Now to do "
			"some real work..." << endl;
	srand(time(0));
	bool running[] = {
			true, true, true, true, true, true, true,
			true, true, true, true, true, true, true };
	const size_t num_threads = sizeof(running) / sizeof(running[0]);
	size_t i;
	for (i = 0; i < num_threads; ++i) {
		if (int err = create_thread(worker_thread, running + i)) {
			cerr << "Failed to create thread " << i <<
					": error code " << err << endl;
			return 1;
		}
	}

	// Test the 'running' flags every second until we find that they're
	// all turned off, indicating that all threads are stopped.
	cout.put('W'); cout.flush(); // indicate waiting for completion
	do {
		sleep(1);
		i = 0;
		while (i < num_threads && !running[i]) ++i;
	}
	while (i < num_threads);
	cout << endl << "All threads stopped!" << endl;

	// Shut it all down...
	delete poolptr;
	cout << endl;
#else
	(void)argc;		// warning squisher
	cout << argv[0] << " requires that threads be enabled!" << endl;
#endif

	return 0;
}

Changes to lib/tcp_connection.cpp.




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

26
27
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
56
57


58




59




60

61



62
63
64





65





66





67
68




69
70
71





72
73


74



75






76

77

78



79





80
81
82
83
84
85

86
87
88

89




90
91
92






93






94
95


96
97
98

99






100
101





102
103
104

105
106


107



108
109
110



111

112


113
114
115
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

144

145

146
147
148
149



150
151
152


153
154
155
156











157
158
159




/***********************************************************************
 tcp_connection.cpp - Implements the TCPConnection class.

 Copyright (c) 2007-2008 by Educational Technology Resources, Inc.
 Others may also hold copyrights on code in this file.  See the
 CREDITS.txt file in the top directory of the distribution for details.

 This file is part of MySQL++.

 MySQL++ is free software; you can redistribute it and/or modify it
 under the terms of the GNU Lesser General Public License as published
 by the Free Software Foundation; either version 2.1 of the License, or
 (at your option) any later version.

 MySQL++ is distributed in the hope that it will be useful, but WITHOUT
 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
 License for more details.

 You should have received a copy of the GNU Lesser General Public
 License along with MySQL++; if not, write to the Free Software
 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
 USA
***********************************************************************/


#define MYSQLPP_NOT_HEADER
#include "common.h"
#include "tcp_connection.h"

#include "exceptions.h"

#if !defined(MYSQLPP_PLATFORM_WINDOWS)
#	include <netdb.h>
#	include <arpa/inet.h>
#endif

#include <ctype.h>
#include <stdlib.h>
#include <climits>

using namespace std;

namespace mysqlpp {


bool

TCPConnection::connect(const char* addr, const char* db,
		const char* user, const char* pass)












{

	error_message_.clear();

	unsigned int port = 0;
	string address;
	if (addr) {
		address = addr;
		if (!parse_address(address, port, error_message_)) {
			return false;


		}




	}






	if (error_message_.empty()) {



		return Connection::connect(db, address.c_str(), user, pass, port);
	}
	else {





		if (throw_exceptions()) {





			throw ConnectionFailed(error_message_.c_str());





		}
		else {




			return false;
		}
	}





}







bool






TCPConnection::parse_address(std::string& addr, unsigned int& port,

		std::string& error)

{



	error.clear();





	
	// Pull off service name or port number, if any
	string service;
	if (addr[0] == '[') {
		// Might be IPv6 address plus port/service in RFC 2732 form.
		string::size_type pos = addr.find(']');

		if ((pos == string::npos) ||
				(addr.find(':', pos + 1) != (pos + 1)) ||
				(addr.find_first_of("[]", pos + 2) != string::npos)) {

			error = "Malformed IPv6 [address]:service combination";




			return false;
		}







		// We can separate address from port/service now






		service = addr.substr(pos + 2);
		addr = addr.substr(1, pos - 1);



		// Ensure that address part is empty or has at least two colons
		if (addr.size() &&

				(((pos = addr.find(':')) == string::npos) ||






				(addr.find(':', pos + 1) == string::npos))) {
			error = "IPv6 literal needs at least two colons";





			return false;
		}
	}

	else {
		// Can only be IPv4 address, so check for 0-1 colons


		string::size_type pos = addr.find(':');



		if (pos != string::npos) {
			if (addr.find(':', pos + 1) != string::npos) {
				error = "IPv4 address:service combo can have only one colon";



				return false;

			}


			
			service = addr.substr(pos + 1);
			addr = addr.substr(0, pos);
		}
	}





	// Turn service into a port number, if it was given.  If not, don't
	// overwrite port because it could have a legal value passed in from


	// Connection.

	if (!service.empty()) {





		if (isdigit(service[0])) {





			port = atoi(service.c_str());
			if ((port < 1) || (port > USHRT_MAX)) {
				error = "Invalid TCP port number " + service;



				return false;
			}
		}
		else {
			servent* pse = getservbyname(service.c_str(), "tcp");



			if (pse) {





				port = ntohs(pse->s_port);




			}
			else {
				error = "Failed to look up TCP service " + service;



				return false;
			}
		}




	}






	// Ensure that there are only alphanumeric characters, dots,
	// dashes and colons in address.  Anything else must be an error.

	for (string::const_iterator it = addr.begin(); it != addr.end(); ++it) {

		string::value_type c = *it;

		if (!(isalnum(c) || (c == '.') || (c == '-') || (c == ':'))) {
			error = "Bad character '";
			error += c;
			error += "' in TCP/IP address";



			return false;
		}
	}



	return true;
}













} // end namespace mysqlpp


>
>
>

<
|
|
|
|



















>
|
<
<

|

<
<
<
<
<
|
<
<
<
<



|
<
>
|
|
>
>
>
>
>
>
>
>
>
>
>
>
|
>
|
|
<
<
|
<
<
|
>
>
|
>
>
>
>
|
>
>
>
>
|
>
|
>
>
>
|

|
>
>
>
>
>
|
>
>
>
>
>
|
>
>
>
>
>
|
|
>
>
>
>
|
|
|
>
>
>
>
>
|

>
>
|
>
>
>
|
>
>
>
>
>
>
|
>
|
>
|
>
>
>
|
>
>
>
>
>
|
|
<
<
|
|
>
|
<
|
>
|
>
>
>
>
|
|

>
>
>
>
>
>
|
>
>
>
>
>
>
|
<
>
>
|
|
|
>
|
>
>
>
>
>
>
|
<
>
>
>
>
>
|
|
|
>
|
<
>
>
|
>
>
>
|
<
<
>
>
>
|
>
|
>
>
|
|
<
|
|
>
>
|
>
>
|
|
>
>
|
>
|
>
>
>
>
>
|
>
>
>
>
>
|
<
<
>
>
>
|
|
|
|
|
>
>
>
|
>
>
>
>
>
|
>
>
>
>
|
|
<
>
>
>
|
|
|
>
>
>
>

>
>
>
|
>
>
|
<
>
|
>
|
>
|
<
<
<
>
>
>
|
|
|
>
>
|
|
|

>
>
>
>
>
>
>
>
>
>
>



>
1
2
3
4

5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
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
56


57


58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
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
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
191
192
193

194
195
196
197
198
199
200


201
202
203
204
205
206
207
208
209
210

211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
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
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
311
/// \file tiny_int.h
/// \brief Declares class for holding a SQL TINYINT

/***********************************************************************

 Copyright (c) 1998 by Kevin Atkinson, (c) 1999-2001 by MySQL AB, and
 (c) 2004-2007 by Educational Technology Resources, Inc.  Others may
 also hold copyrights on code in this file.  See the CREDITS.txt file
 in the top directory of the distribution for details.

 This file is part of MySQL++.

 MySQL++ is free software; you can redistribute it and/or modify it
 under the terms of the GNU Lesser General Public License as published
 by the Free Software Foundation; either version 2.1 of the License, or
 (at your option) any later version.

 MySQL++ is distributed in the hope that it will be useful, but WITHOUT
 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
 License for more details.

 You should have received a copy of the GNU Lesser General Public
 License along with MySQL++; if not, write to the Free Software
 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
 USA
***********************************************************************/

#if !defined(MYSQLPP_TINY_INT_H)
#define MYSQLPP_TINY_INT_H



#include "common.h"






#include <ostream>





namespace mysqlpp {

/// \brief Class for holding an SQL \c TINYINT value

///
/// This is required because the closest C++ type, \c char, doesn't
/// have all the right semantics.  For one, inserting a \c char into a
/// stream won't give you a number.  For another, if you don't specify
/// signedness explicitly, C++ doesn't give a default, so it's signed
/// on some platforms, unsigned on others.
///
/// The template parameter is intended to allow instantiating it as
/// tiny_int<unsigned char> to hold \c TINYINT \c UNSIGNED values.
/// There's nothing stopping you from using any other integer type if
/// you want to be perverse, but please don't do that.
///
/// Several of the functions below accept an \c int argument, but
/// internally we store the data as a \c char by default. Beware of
/// integer overflows!

template <typename VT = signed char>
class tiny_int
{


public:


	//// Type aliases
	typedef tiny_int<VT> this_type;	///< alias for this object's type
	typedef VT value_type;			///< alias for type of internal value

	/// \brief Default constructor
	///
	/// Value is uninitialized
	tiny_int() { }
	
	/// \brief Create object from any integral type that can be
	/// converted to a \c short \c int.
	tiny_int(value_type v) :
	value_(value_type(v))
	{
	}
	
	/// \brief Return truthiness of value
	operator bool() const
	{
		return value_;
	}

	/// \brief Return value as an \c int.
	operator int() const
	{
		return static_cast<int>(value_);
	}

	/// \brief Return raw data value with no size change
	operator value_type() const
	{
		return value_;
	}

	/// \brief Assign a new value to the object.
	this_type& operator =(int v)
	{
		value_ = static_cast<value_type>(v);
		return *this;
	}

	/// \brief Add another value to this object
	this_type& operator +=(int v)
	{
		value_ += static_cast<value_type>(v);
		return *this;
	}

	/// \brief Subtract another value to this object
	this_type& operator -=(int v)
	{
		value_ -= static_cast<value_type>(v);
		return *this;
	}

	/// \brief Multiply this value by another object
	this_type& operator *=(int v)
	{
		value_ *= static_cast<value_type>(v);
		return *this;
	}

	/// \brief Divide this value by another object
	this_type& operator /=(int v)
	{
		value_ /= static_cast<value_type>(v);
		return *this;
	}

	/// \brief Divide this value by another object and store the
	/// remainder
	this_type& operator %=(int v)
	{
		value_ %= static_cast<value_type>(v);
		return *this;
	}

	/// \brief Bitwise AND this value by another value
	this_type& operator &=(int v)
	{
		value_ &= static_cast<value_type>(v);
		return *this;
	}



	/// \brief Bitwise OR this value by another value
	this_type& operator |=(int v)
	{
		value_ |= static_cast<value_type>(v);

		return *this;
	}

	/// \brief Bitwise XOR this value by another value
	this_type& operator ^=(int v)
	{
		value_ ^= static_cast<value_type>(v);
		return *this;
	}

	/// \brief Shift this value left by \c v positions
	this_type& operator <<=(int v)
	{
		value_ <<= static_cast<value_type>(v);
		return *this;
	}

	/// \brief Shift this value right by \c v positions
	this_type& operator >>=(int v)
	{
		value_ >>= static_cast<value_type>(v);
		return *this;
	}


	/// \brief Add one to this value and return that value
	this_type& operator ++()
	{
		++value_;
		return *this;
	}

	/// \brief Subtract one from this value and return that value
	this_type& operator --()
	{
		--value_;
		return *this;
	}


	/// \brief Add one to this value and return the previous value
	this_type operator ++(int)
	{
		this_type tmp = value_;
		++value_;
		return tmp;
	}

	/// \brief Subtract one from this value and return the previous
	/// value

	this_type operator --(int)
	{
		this_type tmp = value_;
		--value_;
		return tmp;
	}



	/// \brief Return this value minus \c i
	this_type operator -(const this_type& i) const
	{
		return value_ - i.value_;
	}
	
	/// \brief Return this value plus \c i
	this_type operator +(const this_type& i) const
	{
		return value_ + i.value_;

	}
	
	/// \brief Return this value multiplied by \c i
	this_type operator *(const this_type& i) const
	{
		return value_ * i.value_;
	}
	
	/// \brief Return this value divided by \c i
	this_type operator /(const this_type& i) const
	{
		return value_ / i.value_;
	}
	
	/// \brief Return the modulus of this value divided by \c i
	this_type operator %(const this_type& i) const
	{
		return value_ % i.value_;
	}
	
	/// \brief Return this value bitwise OR'd by \c i
	this_type operator |(const this_type& i) const
	{
		return value_ | i.value_;
	}
	


	/// \brief Return this value bitwise AND'd by \c i
	this_type operator &(const this_type& i) const
	{
		return value_ & i.value_;
	}
	
	/// \brief Return this value bitwise XOR'd by \c i
	this_type operator ^(const this_type& i) const
	{
		return value_ ^ i.value_;
	}
	
	/// \brief Return this value bitwise shifted left by \c i
	this_type operator <<(const this_type& i) const
	{
		return value_ << i.value_;
	}
	
	/// \brief Return this value bitwise shifted right by \c i
	this_type operator >>(const this_type& i) const
	{
		return value_ >> i.value_;
	}


	/// \brief Check for equality
	bool operator ==(const this_type& i) const
	{
		return value_ == i.value_;
	}

	/// \brief Check for inequality
	bool operator !=(const this_type& i) const
	{
		return value_ != i.value_;
	}

	/// \brief Check that this object is less than another
	bool operator <(const this_type& i) const
	{
		return value_ < i.value_;
	}


	/// \brief Check that this object is greater than another
	bool operator >(const this_type& i) const
	{
		return value_ > i.value_;
	}




	/// \brief Check this object is less than or equal to another
	bool operator <=(const this_type& i) const
	{
		return value_ <= i.value_;
	}

	/// \brief Check this object is greater than or equal to another
	bool operator >=(const this_type& i) const
	{
		return value_ >= i.value_;
	}

private:
	value_type value_;
};

/// \brief Insert a \c tiny_int into a C++ stream
template <typename VT>
std::ostream& operator <<(std::ostream& os, tiny_int<VT> i)
{
	os << static_cast<int>(i);
	return os;
}

} // end namespace mysqlpp

#endif

Changes to lib/tcp_connection.h.

1
2

3
4

5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27

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
56
57


58
59
60
61
62
63
64
65
66
67
68
69
70
71

72
73
74

75






76


77
78
79





80
81
82
83


84


85
86
87
88
89




90






91
92

93



94
95
96
97

98
99
100
101
102
103
104

105
106
107
108

109

110
111
112
113
114
115
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
/// \file tcp_connection.h
/// \brief Declares the TCPConnection class.


/***********************************************************************

 Copyright (c) 2007-2008 by Educational Technology Resources, Inc.
 Others may also hold copyrights on code in this file.  See the
 CREDITS.txt file in the top directory of the distribution for details.

 This file is part of MySQL++.

 MySQL++ is free software; you can redistribute it and/or modify it
 under the terms of the GNU Lesser General Public License as published
 by the Free Software Foundation; either version 2.1 of the License, or
 (at your option) any later version.

 MySQL++ is distributed in the hope that it will be useful, but WITHOUT
 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
 License for more details.

 You should have received a copy of the GNU Lesser General Public
 License along with MySQL++; if not, write to the Free Software
 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
 USA
***********************************************************************/

#if !defined(MYSQLPP_TCP_CONNECTION_H)

#define MYSQLPP_TCP_CONNECTION_H




#include "connection.h"


namespace mysqlpp {

/// \brief Specialization of \c Connection for TCP/IP
///
/// This class just simplifies the connection creation interface of
/// \c Connection.  It does not add new functionality.















class MYSQLPP_EXPORT TCPConnection : public Connection
{
public:
	/// \brief Create object without connecting it to the MySQL server.
	TCPConnection() :
	Connection()
	{


	}






	/// \brief Create object and connect to database server over TCP/IP
	/// in one step.
	///

	/// \param addr TCP/IP address of server, in either dotted quad form
	///     or as a host or domain name; may be followed by a colon and
	///     a port number or service name to override default port
	/// \param db name of database to use

	/// \param user user name to log in under, or 0 to use the user
	///		name the program is running under
	/// \param password password to use when logging in


	///
	/// \b BEWARE: These parameters are not in the same order as those
	/// in the corresponding constructor for Connection.  This is a
	/// feature, not a bug. :)
	TCPConnection(const char* addr, const char* db = 0, const char* user = 0,
			const char* password = 0) :
	Connection()
	{
		connect(addr, db, user, password);
	}

	/// \brief Establish a new connection using the same parameters as
	/// an existing connection.
	///

	/// \param other pre-existing connection to clone
	TCPConnection(const TCPConnection& other) :
	Connection(other)

	{






	}



	/// \brief Destroy object
	~TCPConnection() { }






	/// \brief Connect to database after object is created.
	///
	/// It's better to use the connect-on-create constructor if you can.


	/// See its documentation for the meaning of these parameters.


	///
	/// If you call this method on an object that is already connected
	/// to a database server, the previous connection is dropped and a
	/// new connection is established.
	bool connect(const char* addr = 0, const char* db = 0,




			const char* user = 0, const char* password = 0);







	/// \brief Break the given TCP/IP address up into a separate address

	/// and port form



	///
	/// Does some sanity checking on the address.  Only intended to
	/// try and prevent library misuse, not ensure that the address can
	/// actually be used to contact a server.

	///
	/// It understands the following forms:
	///
	///	- 1.2.3.4
	///
	/// - a.b.com:89
	///

	/// - d.e.fr:mysvcname
	///
	/// It also understands IPv6 addresses, but to avoid confusion
	/// between the colons they use and the colon separating the address

	/// part from the service/port part, they must be in RFC 2732 form.

	/// Example: \c [2010:836B:4179::836B:4179]:1234
	///
	/// \param addr the address and optional port/service combo to check
	/// on input, and the verified address on successful return
	/// \param port the port number (resolved from the service name if
	/// necessary) on successful return
	/// \param error on false return, reason for failure is placed here
	///
	/// \return false if address fails to pass sanity checks
	static bool parse_address(std::string& addr, unsigned int& port,
			std::string& error);






private:


	/// \brief Provide uncallable versions of the parent class ctors we
	/// don't want to provide so we don't get warnings about hidden
	/// overloads with some compilers
	TCPConnection(bool) { }
	TCPConnection(const char*, const char*, const char*, const char*,
			unsigned int) { }


	/// \brief Explicitly override parent class version so we don't get
	/// complaints about hidden overloads with some compilers
	bool connect(const char*, const char*, const char*, const char*,



			unsigned int) { return false; }

};













} // end namespace mysqlpp




#endif // !defined(MYSQLPP_TCP_CONNECTION_H)


|
|
>

<
>
|
|
|



















|
>
|
>

>
>
|
>

|

|
<
<
<
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
|
|
<
|
|
|
|
>
>
|
>
>
>
>
>
|
|
<
<
>
|
|
<
|
>
|
|
|
>
>
|
|
<
<
|
|
|
|
|
<
|
<
|
<
>
|
<
<
>
|
>
>
>
>
>
>
|
>
>
|
<
<
>
>
>
>
>
|
|
<
<
>
>
|
>
>
|
<
<
|
|
>
>
>
>
|
>
>
>
>
>
>
|
<
>
|
>
>
>
|
|
<
<
>
|
|
<
<
<
|
<
>
|
<
<
|
>
|
>
|
<
<
<
<
<
<
<
<
<
|
>
>
>
>
>
|
|
>
>
|
|
<
|
<
|
>
|
<
<
<
>
>
>
|
>
|
>
>
>
>
>
>
>
|
>
>
>
>
|
|
>
>
>
|
|
>
|
1
2
3
4

5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
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
56
57

58
59
60
61
62
63
64
65
66
67
68
69
70
71


72
73
74

75
76
77
78
79
80
81
82
83


84
85
86
87
88

89

90

91
92


93
94
95
96
97
98
99
100
101
102
103
104


105
106
107
108
109
110
111


112
113
114
115
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
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
191
192
/***********************************************************************
 dbinfo.cpp - Example showing how to request information about the
	database schema, such as table names, column types, etc.


 Copyright (c) 1998 by Kevin Atkinson, (c) 1999-2001 by MySQL AB, and
 (c) 2004-2009 by Educational Technology Resources, Inc.  Others may
 also hold copyrights on code in this file.  See the CREDITS.txt file
 in the top directory of the distribution for details.

 This file is part of MySQL++.

 MySQL++ is free software; you can redistribute it and/or modify it
 under the terms of the GNU Lesser General Public License as published
 by the Free Software Foundation; either version 2.1 of the License, or
 (at your option) any later version.

 MySQL++ is distributed in the hope that it will be useful, but WITHOUT
 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
 License for more details.

 You should have received a copy of the GNU Lesser General Public
 License along with MySQL++; if not, write to the Free Software
 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
 USA
***********************************************************************/

#include "cmdline.h"
#include "printdata.h"

#include <mysql++.h>

#include <iomanip>
#include <iostream>
#include <string>
#include <vector>

using namespace std;





// Insert a bar into the stream with the given query string centered
static void
separator(ostream& os, string qstr)
{
	string sep("========================================"
			"========================================");
	if (qstr.size()) {
		string::size_type start = (sep.size() - qstr.size()) / 2;
		sep.replace(start - 1, 1, 1, ' ');
		sep.replace(start, qstr.size(), qstr);
		sep.replace(start + qstr.size(), 1, 1, ' ');
		os << "\n\n";
	}
	os << sep << endl;
}



// Print out the MySQL server version
static void
show_mysql_version(mysqlpp::Connection& con)
{
	separator(cout, "");
    cout << "MySQL version: " << con.client_version();
}


// Print out the names of all the databases managed by the server
static void
show_databases(mysqlpp::Connection& con)
{
	mysqlpp::Query query = con.query("show databases");


	separator(cout, query.str());
	mysqlpp::StoreQueryResult res = query.store();


	cout << "Databases found: " << res.size();
	cout.setf(ios::left);
	mysqlpp::StoreQueryResult::iterator rit;
	for (rit = res.begin(); rit != res.end(); ++rit) {
		cout << "\n\t" << (*rit)[0];
	}
}




// Print information about each of the tables we found
static void
show_table_info(mysqlpp::Connection& con, const vector<string>& tables)
{
	vector<string>::const_iterator it;

	for (it = tables.begin(); it != tables.end(); ++it) {

		mysqlpp::Query query = con.query();

		query << "describe " << *it;
		separator(cout, query.str());


		mysqlpp::StoreQueryResult res = query.store();

		size_t columns = res.num_fields();
		vector<size_t> widths;
		for (size_t i = 0; i < columns; ++i) {
			string s = res.field_name(int(i));
			if (s.compare("field") == 0) {
				widths.push_back(22);
			}
			else if (s.compare("type") == 0) {
				widths.push_back(20);
			}


			else if (s.compare("null") == 0) {
				widths.push_back(4);
			}
			else if (s.compare("key") == 0) {
				widths.push_back(3);
			}
			else if (s.compare("extra") == 0) {


				widths.push_back(0);
			}
			else {
				widths.push_back(15);
			}



			if (widths[i]) {
				cout << '|' << setw(widths[i]) << 
						res.field_name(int(i)) << '|';
			}
		}
		cout << endl;

		mysqlpp::StoreQueryResult::iterator rit;
		for (rit = res.begin(); rit != res.end(); ++rit) {
			for (unsigned int i = 0; i < columns; ++i) {
				if (widths[i]) {
					cout << ' ' << setw(widths[i]) <<
							(*rit)[i].c_str() << ' ';
				}

			}
			cout << endl;
		}
	}
}




// Print out the names of all tables in the sample database, and
// return the list of tables.
static void



show_tables(mysqlpp::Connection& con)

{
	mysqlpp::Query query = con.query("show tables");


	separator(cout, query.str());
	mysqlpp::StoreQueryResult res = query.store();

	cout << "Tables found: " << res.size();
	cout.setf(ios::left);









	vector<string> tables;
	mysqlpp::StoreQueryResult::iterator rit;
	for (rit = res.begin(); rit != res.end(); ++rit) {
		string tbl((*rit)[0]);
		cout << "\n\t" << tbl;
		tables.push_back(tbl);
	}

	show_table_info(con, tables);
}



// Call all the above functions in sequence

int
main(int argc, char* argv[])
{



	// Get database access parameters from command line
	mysqlpp::examples::CommandLine cmdline(argc, argv);
	if (!cmdline) {
		return 1;
	}

	try {
		// Connect to server, then dump a bunch of stuff we find on it
		mysqlpp::Connection con(mysqlpp::examples::db_name,
				cmdline.server(), cmdline.user(), cmdline.pass());
		show_mysql_version(con);
		show_databases(con);
		show_tables(con);
	}
	catch (const mysqlpp::BadQuery& er) {
		// Handle any query errors
		cerr << "Query error: " << er.what() << endl;
		return -1;
	}
	catch (const mysqlpp::Exception& er) {
		// Catch-all for any other MySQL++ exceptions
		cerr << "Error: " << er.what() << endl;
		return -1;
	}

	return 0;
}

Changes to lib/tiny_int.h.


1



2
3
4



5


6


7
8


9
10

11


12


13


14
15
16
17
18
19
20
21
22
23
24
25
26

27



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
56

57
58
59
60
61
62
63
64
65
66
67
68
69



70
71
72
73
74


75
76
77
78










79
80



81
82
83
84
85
86
87
88

89
90
91

92
93
94

95
96
97
















98
99
100
101

102
103
104
105

106
107
108

109
110
111
112

113
114
115

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


191
192

193


194


195
196
197
198
199


200
201
202

203


204


205


206


207


208


209


210


211


212


213
214


215
216


217


218
219
220


221
222


223


224
225
226


227
228


229


230
231
232


233
234

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


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
311


/// \file tiny_int.h



/// \brief Declares class for holding a SQL TINYINT

/***********************************************************************



 Copyright (c) 1998 by Kevin Atkinson, (c) 1999-2001 by MySQL AB, and


 (c) 2004-2007 by Educational Technology Resources, Inc.  Others may


 also hold copyrights on code in this file.  See the CREDITS.txt file
 in the top directory of the distribution for details.



 This file is part of MySQL++.




 MySQL++ is free software; you can redistribute it and/or modify it


 under the terms of the GNU Lesser General Public License as published


 by the Free Software Foundation; either version 2.1 of the License, or
 (at your option) any later version.

 MySQL++ is distributed in the hope that it will be useful, but WITHOUT
 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
 License for more details.

 You should have received a copy of the GNU Lesser General Public
 License along with MySQL++; if not, write to the Free Software
 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
 USA
***********************************************************************/





#if !defined(MYSQLPP_TINY_INT_H)








#define MYSQLPP_TINY_INT_H


#include "common.h"



#include <ostream>



namespace mysqlpp {




/// \brief Class for holding an SQL \c TINYINT value
///
/// This is required because the closest C++ type, \c char, doesn't
/// have all the right semantics.  For one, inserting a \c char into a


/// stream won't give you a number.  For another, if you don't specify
/// signedness explicitly, C++ doesn't give a default, so it's signed
/// on some platforms, unsigned on others.
///
/// The template parameter is intended to allow instantiating it as
/// tiny_int<unsigned char> to hold \c TINYINT \c UNSIGNED values.
/// There's nothing stopping you from using any other integer type if
/// you want to be perverse, but please don't do that.
///

/// Several of the functions below accept an \c int argument, but
/// internally we store the data as a \c char by default. Beware of


/// integer overflows!
















template <typename VT = signed char>
class tiny_int
{

public:
	//// Type aliases
	typedef tiny_int<VT> this_type;	///< alias for this object's type
	typedef VT value_type;			///< alias for type of internal value

	/// \brief Default constructor
	///
	/// Value is uninitialized
	tiny_int() { }
	
	/// \brief Create object from any integral type that can be
	/// converted to a \c short \c int.
	tiny_int(value_type v) :



	value_(value_type(v))
	{
	}
	
	/// \brief Return truthiness of value


	operator bool() const
	{
		return value_;
	}











	/// \brief Return value as an \c int.



	operator int() const
	{
		return static_cast<int>(value_);
	}

	/// \brief Return raw data value with no size change
	operator value_type() const
	{

		return value_;
	}


	/// \brief Assign a new value to the object.
	this_type& operator =(int v)
	{

		value_ = static_cast<value_type>(v);
		return *this;
	}

















	/// \brief Add another value to this object
	this_type& operator +=(int v)
	{

		value_ += static_cast<value_type>(v);
		return *this;
	}


	/// \brief Subtract another value to this object
	this_type& operator -=(int v)
	{

		value_ -= static_cast<value_type>(v);
		return *this;
	}


	/// \brief Multiply this value by another object
	this_type& operator *=(int v)
	{

		value_ *= static_cast<value_type>(v);




		return *this;
	}






















	/// \brief Divide this value by another object






	this_type& operator /=(int v)
	{
		value_ /= static_cast<value_type>(v);
		return *this;
	}


	/// \brief Divide this value by another object and store the
	/// remainder
	this_type& operator %=(int v)
	{
		value_ %= static_cast<value_type>(v);
		return *this;
	}







	/// \brief Bitwise AND this value by another value
	this_type& operator &=(int v)
	{

		value_ &= static_cast<value_type>(v);
		return *this;
	}


	/// \brief Bitwise OR this value by another value
	this_type& operator |=(int v)
	{

		value_ |= static_cast<value_type>(v);
		return *this;
	}


	/// \brief Bitwise XOR this value by another value
	this_type& operator ^=(int v)
	{

		value_ ^= static_cast<value_type>(v);





		return *this;
	}











	/// \brief Shift this value left by \c v positions
	this_type& operator <<=(int v)


	{
		value_ <<= static_cast<value_type>(v);

		return *this;


	}



	/// \brief Shift this value right by \c v positions
	this_type& operator >>=(int v)


	{
		value_ >>= static_cast<value_type>(v);
		return *this;


	}



	/// \brief Add one to this value and return that value
	this_type& operator ++()

	{


		++value_;


		return *this;


	}





	/// \brief Subtract one from this value and return that value


	this_type& operator --()


	{
		--value_;
		return *this;


	}



	/// \brief Add one to this value and return the previous value
	this_type operator ++(int)


	{
		this_type tmp = value_;
		++value_;
		return tmp;


	}



	/// \brief Subtract one from this value and return the previous

	/// value


	this_type operator --(int)


	{
		this_type tmp = value_;
		--value_;
		return tmp;
	}



	/// \brief Return this value minus \c i
	this_type operator -(const this_type& i) const

	{


		return value_ - i.value_;


	}


	


	/// \brief Return this value plus \c i


	this_type operator +(const this_type& i) const


	{


		return value_ + i.value_;


	}


	


	/// \brief Return this value multiplied by \c i
	this_type operator *(const this_type& i) const


	{
		return value_ * i.value_;


	}


	
	/// \brief Return this value divided by \c i
	this_type operator /(const this_type& i) const


	{
		return value_ / i.value_;


	}


	
	/// \brief Return the modulus of this value divided by \c i
	this_type operator %(const this_type& i) const


	{
		return value_ % i.value_;


	}


	
	/// \brief Return this value bitwise OR'd by \c i
	this_type operator |(const this_type& i) const


	{
		return value_ | i.value_;

	}


	


	/// \brief Return this value bitwise AND'd by \c i
	this_type operator &(const this_type& i) const


	{
		return value_ & i.value_;


	}


	
	/// \brief Return this value bitwise XOR'd by \c i
	this_type operator ^(const this_type& i) const


	{
		return value_ ^ i.value_;


	}


	
	/// \brief Return this value bitwise shifted left by \c i
	this_type operator <<(const this_type& i) const


	{
		return value_ << i.value_;


	}


	


	/// \brief Return this value bitwise shifted right by \c i


	this_type operator >>(const this_type& i) const


	{
		return value_ >> i.value_;


	}



	/// \brief Check for equality
	bool operator ==(const this_type& i) const


	{
		return value_ == i.value_;


	}



	/// \brief Check for inequality
	bool operator !=(const this_type& i) const


	{
		return value_ != i.value_;


	}



	/// \brief Check that this object is less than another
	bool operator <(const this_type& i) const
	{
		return value_ < i.value_;

	}





	/// \brief Check that this object is greater than another


	bool operator >(const this_type& i) const


	{


		return value_ > i.value_;


	}



	/// \brief Check this object is less than or equal to another
	bool operator <=(const this_type& i) const


	{
		return value_ <= i.value_;


	}





	/// \brief Check this object is greater than or equal to another


	bool operator >=(const this_type& i) const


	{
		return value_ >= i.value_;


	}



private:
	value_type value_;
};



/// \brief Insert a \c tiny_int into a C++ stream
template <typename VT>

std::ostream& operator <<(std::ostream& os, tiny_int<VT> i)


{
	os << static_cast<int>(i);
	return os;


}


} // end namespace mysqlpp

#endif

>
|
>
>
>
|

|
>
>
>
|
>
>
|
>
>
|
<
>
>

|
>

>
>
|
>
>
|
>
>
|
|

|
|
|
<

<
<
<
<
<
>

>
>
>
|
>
>
>
>
>
>
>
>
|
|
>
|
|
>
>
|
|
>
>
|
>
>
>
|
|
<
<
|
>
>
|
|
|
|
|
|
|
|
<
>
|
|
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
|
|
<
>
|
|
|
|
|
|
|
|
|
|
|
|
|
>
>
>
|
<
<
|
<
>
>
|
<
<
<
>
>
>
>
>
>
>
>
>
>
|
|
>
>
>
|
<
<
<
|
|
|
<
>
|
<
|
>
|
|
<
>
|
|
<
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
|
|
<
>
|
|
<
|
>
|
|
<
>
|
|
<
|
>
|
|
<
>
|
>
>
>
>
|
<
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

>
|
>
>
>
>
>
>
|
|
<
|
|
>

<
|
<
|
|
<
|
>
>
>
>
>
>
|
|
|
<
>
|
|
<
|
>
|
|
<
>
|
|
<
|
>
|
|
<
>
|
>
>
>
>
>
|
<
>
>
>
>
>
>
>
>
>
>
|
|
|
>
>
|
<
>
|
>
>
|
>
>

<
<
>
>
|
<
<
>
>
|
>
>

<
|
>
|
>
>
|
>
>
|
>
>
|
>
>

>
>
|
>
>
|
>
>
|
<
<
>
>
|
>
>

<
<
>
>
|
<
<
<
>
>
|
>
>

<
>
|
>
>
|
>
>
|
|
|
<
|
>
>

<
|
>
|
>
>
|
>
>
|
>
>
|
>
>
|
>
>
|
>
>
|
>
>
|
>
>
|
>
>
|
>
>
|
<
>
>
|
<
>
>
|
>
>
|
<
<
>
>
|
<
>
>
|
>
>
|
<
<
>
>
|
<
>
>
|
>
>
|
<
<
>
>
|
|
>
|
>
>
|
>
>
|
<
>
>
|
<
>
>
|
>
>
|
<
<
>
>
|
<
>
>
|
>
>
|
<
<
>
>
|
<
>
>
|
>
>
|
>
>
|
>
>
|
>
>
|
<
>
>
|
>
>

<
<
>
>
|
<
>
>
|
>
>

<
<
>
>
|
<
>
>
|
>
>

|
|
|
|
>
|
>
>

>
>
|
>
>
|
>
>
|
>
>
|
>
>
|
>
>

<
<
>
>
|
<
>
>
|
>
>

>
>
|
>
>
|
>
>
|
<
>
>
|
>
>

<
<
<
>
>

<
|
>
|
>
>
|
<
<
>
>
|
>

<

|
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

19
20
21
22
23
24
25
26
27
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
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70


71
72
73
74
75
76
77
78
79
80
81

82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105

106
107
108
109
110
111
112
113
114
115
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



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
191
192
193
194
195

196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226

227
228
229
230

231

232
233

234
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
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
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
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
372
373
374
375
376
377
378
379
380
381
382
383
384

385
386
387

388
389
390
391
392
393


394
395
396

397
398
399
400
401
402


403
404
405

406
407
408
409
410
411


412
413
414
415
416
417
418
419
420
421
422
423

424
425
426

427
428
429
430
431
432


433
434
435

436
437
438
439
440
441


442
443
444

445
446
447
448
449
450
451
452
453
454
455
456
457
458
459

460
461
462
463
464
465


466
467
468

469
470
471
472
473
474


475
476
477

478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510


511
512
513

514
515
516
517
518
519
520
521
522
523
524
525
526
527
528

529
530
531
532
533
534



535
536
537

538
539
540
541
542
543


544
545
546
547
548

549
550
551
# =========================================================================
#     This makefile was generated by
#     Bakefile 0.2.5 (http://www.bakefile.org)
#     Do not modify, all changes will be overwritten!
# =========================================================================



# -------------------------------------------------------------------------
# These are configurable options:
# -------------------------------------------------------------------------

#  
AR ?= ar

#  
RANLIB ?= ranlib


# C++ compiler 
CXX = g++

# Standard flags for C++ 
CXXFLAGS ?= 

# Standard preprocessor flags (common for CC and CXX) 
CPPFLAGS ?= 

# Standard linker flags 
LDFLAGS ?= 

# Type of compiled binaries [debug,release]
BUILD ?= debug



# -------------------------------------------------------------------------
# Do not modify the rest of this file!
# -------------------------------------------------------------------------







### Variables: ###

CPPDEPS = -MT$@ -MF`echo $@ | sed -e 's,\.o$$,.d,'` -MD -MP
SSQLS2PARSE_CXXFLAGS = $(__DEBUGINFO) -Ilib -I/usr/include/mysql \
	-I/usr/include/mysql++ -I. $(CPPFLAGS) $(CXXFLAGS)
SSQLS2PARSE_OBJECTS =  \
	ssqls2parse_parsev2.o
SSQLSXLAT_CXXFLAGS = $(__DEBUGINFO) -Ilib -I/usr/include/mysql \
	-I/usr/include/mysql++ $(CPPFLAGS) $(CXXFLAGS)
SSQLSXLAT_OBJECTS =  \
	ssqlsxlat_genv2.o \
	ssqlsxlat_main.o
TEST_ARRAY_INDEX_CXXFLAGS = $(__DEBUGINFO) -Ilib -I/usr/include/mysql \
	-I/usr/include/mysql++ $(CPPFLAGS) $(CXXFLAGS)
TEST_ARRAY_INDEX_OBJECTS =  \
	test_array_index_array_index.o
TEST_CPOOL_CXXFLAGS = $(__DEBUGINFO) -Ilib -I/usr/include/mysql \
	-I/usr/include/mysql++ $(CPPFLAGS) $(CXXFLAGS)
TEST_CPOOL_OBJECTS =  \
	test_cpool_cpool.o
TEST_DATETIME_CXXFLAGS = $(__DEBUGINFO) -Ilib -I/usr/include/mysql \
	-I/usr/include/mysql++ $(CPPFLAGS) $(CXXFLAGS)
TEST_DATETIME_OBJECTS =  \
	test_datetime_datetime.o
TEST_INTTYPES_CXXFLAGS = $(__DEBUGINFO) -Ilib -I/usr/include/mysql \
	-I/usr/include/mysql++ $(CPPFLAGS) $(CXXFLAGS)
TEST_INTTYPES_OBJECTS =  \
	test_inttypes_inttypes.o
TEST_INSERTPOLICY_CXXFLAGS = $(__DEBUGINFO) -Ilib -I/usr/include/mysql \
	-I/usr/include/mysql++ $(CPPFLAGS) $(CXXFLAGS)
TEST_INSERTPOLICY_OBJECTS =  \


	test_insertpolicy_insertpolicy.o
TEST_MANIP_CXXFLAGS = $(__DEBUGINFO) -Ilib -I/usr/include/mysql \
	-I/usr/include/mysql++ $(CPPFLAGS) $(CXXFLAGS)
TEST_MANIP_OBJECTS =  \
	test_manip_manip.o
TEST_NULL_COMPARISON_CXXFLAGS = $(__DEBUGINFO) -Ilib -I/usr/include/mysql \
	-I/usr/include/mysql++ $(CPPFLAGS) $(CXXFLAGS)
TEST_NULL_COMPARISON_OBJECTS =  \
	test_null_comparison_null_comparison.o
TEST_QUERY_COPY_CXXFLAGS = $(__DEBUGINFO) -Ilib -I/usr/include/mysql \
	-I/usr/include/mysql++ $(CPPFLAGS) $(CXXFLAGS)

TEST_QUERY_COPY_OBJECTS =  \
	test_query_copy_query_copy.o
TEST_QSSQLS_CXXFLAGS = $(__DEBUGINFO) -Ilib -I/usr/include/mysql \
	-I/usr/include/mysql++ $(CPPFLAGS) $(CXXFLAGS)
TEST_QSSQLS_OBJECTS =  \
	test_qssqls_qssqls.o
TEST_QSTREAM_CXXFLAGS = $(__DEBUGINFO) -Ilib -I/usr/include/mysql \
	-I/usr/include/mysql++ $(CPPFLAGS) $(CXXFLAGS)
TEST_QSTREAM_OBJECTS =  \
	test_qstream_qstream.o
TEST_SQLSTREAM_CXXFLAGS = $(__DEBUGINFO) -Ilib -I/usr/include/mysql \
	-I/usr/include/mysql++ $(CPPFLAGS) $(CXXFLAGS)
TEST_SQLSTREAM_OBJECTS =  \
	test_sqlstream_sqlstream.o
TEST_SSQLS2_CXXFLAGS = $(__DEBUGINFO) -Ilib -I/usr/include/mysql \
	-I/usr/include/mysql++ $(CPPFLAGS) $(CXXFLAGS)
TEST_SSQLS2_OBJECTS =  \
	test_ssqls2_ssqls2.o
TEST_STRING_CXXFLAGS = $(__DEBUGINFO) -Ilib -I/usr/include/mysql \
	-I/usr/include/mysql++ $(CPPFLAGS) $(CXXFLAGS)
TEST_STRING_OBJECTS =  \
	test_string_string.o
TEST_TCP_CXXFLAGS = $(__DEBUGINFO) -Ilib -I/usr/include/mysql \
	-I/usr/include/mysql++ $(CPPFLAGS) $(CXXFLAGS)

TEST_TCP_OBJECTS =  \
	test_tcp_tcp.o
TEST_UDS_CXXFLAGS = $(__DEBUGINFO) -Ilib -I/usr/include/mysql \
	-I/usr/include/mysql++ $(CPPFLAGS) $(CXXFLAGS)
TEST_UDS_OBJECTS =  \
	test_uds_uds.o
TEST_WNP_CXXFLAGS = $(__DEBUGINFO) -Ilib -I/usr/include/mysql \
	-I/usr/include/mysql++ $(CPPFLAGS) $(CXXFLAGS)
TEST_WNP_OBJECTS =  \
	test_wnp_wnp.o
EXCOMMON_CXXFLAGS = $(__DEBUGINFO) -Ilib -I/usr/include/mysql \
	-I/usr/include/mysql++ $(CPPFLAGS) $(CXXFLAGS)
EXCOMMON_OBJECTS =  \
	excommon_printdata.o
CGI_JPEG_CXXFLAGS = $(__DEBUGINFO) -Ilib -I/usr/include/mysql \
	-I/usr/include/mysql++ $(CPPFLAGS) $(CXXFLAGS)
CGI_JPEG_OBJECTS =  \
	cgi_jpeg_cgi_jpeg.o


CPOOL_CXXFLAGS = $(__DEBUGINFO) -Ilib -I/usr/include/mysql \

	-I/usr/include/mysql++ $(CPPFLAGS) $(CXXFLAGS)
CPOOL_OBJECTS =  \
	cpool_cpool.o



DBINFO_CXXFLAGS = $(__DEBUGINFO) -Ilib -I/usr/include/mysql \
	-I/usr/include/mysql++ $(CPPFLAGS) $(CXXFLAGS)
DBINFO_OBJECTS =  \
	dbinfo_dbinfo.o
DEADLOCK_CXXFLAGS = $(__DEBUGINFO) -Ilib -I/usr/include/mysql \
	-I/usr/include/mysql++ $(CPPFLAGS) $(CXXFLAGS)
DEADLOCK_OBJECTS =  \
	deadlock_deadlock.o
FIELDINF_CXXFLAGS = $(__DEBUGINFO) -Ilib -I/usr/include/mysql \
	-I/usr/include/mysql++ $(CPPFLAGS) $(CXXFLAGS)
FIELDINF_OBJECTS =  \
	fieldinf_fieldinf.o
FOR_EACH_CXXFLAGS = $(__DEBUGINFO) -Ilib -I/usr/include/mysql \
	-I/usr/include/mysql++ $(CPPFLAGS) $(CXXFLAGS)
FOR_EACH_OBJECTS =  \
	for_each_for_each.o



LOAD_JPEG_CXXFLAGS = $(__DEBUGINFO) -Ilib -I/usr/include/mysql \
	-I/usr/include/mysql++ $(CPPFLAGS) $(CXXFLAGS)
LOAD_JPEG_OBJECTS =  \

	load_jpeg_load_jpeg.o
MULTIQUERY_CXXFLAGS = $(__DEBUGINFO) -Ilib -I/usr/include/mysql \

	-I/usr/include/mysql++ $(CPPFLAGS) $(CXXFLAGS)
MULTIQUERY_OBJECTS =  \
	multiquery_multiquery.o
RESETDB_CXXFLAGS = $(__DEBUGINFO) -Ilib -I/usr/include/mysql \

	-I/usr/include/mysql++ $(CPPFLAGS) $(CXXFLAGS)
RESETDB_OBJECTS =  \
	resetdb_resetdb.o

SIMPLE1_CXXFLAGS = $(__DEBUGINFO) -Ilib -I/usr/include/mysql \
	-I/usr/include/mysql++ $(CPPFLAGS) $(CXXFLAGS)
SIMPLE1_OBJECTS =  \
	simple1_simple1.o
SIMPLE2_CXXFLAGS = $(__DEBUGINFO) -Ilib -I/usr/include/mysql \
	-I/usr/include/mysql++ $(CPPFLAGS) $(CXXFLAGS)
SIMPLE2_OBJECTS =  \
	simple2_simple2.o
SIMPLE3_CXXFLAGS = $(__DEBUGINFO) -Ilib -I/usr/include/mysql \
	-I/usr/include/mysql++ $(CPPFLAGS) $(CXXFLAGS)
SIMPLE3_OBJECTS =  \
	simple3_simple3.o
SSQLS1_CXXFLAGS = $(__DEBUGINFO) -Ilib -I/usr/include/mysql \
	-I/usr/include/mysql++ $(CPPFLAGS) $(CXXFLAGS)
SSQLS1_OBJECTS =  \
	ssqls1_ssqls1.o
SSQLS2_CXXFLAGS = $(__DEBUGINFO) -Ilib -I/usr/include/mysql \
	-I/usr/include/mysql++ $(CPPFLAGS) $(CXXFLAGS)
SSQLS2_OBJECTS =  \

	ssqls2_ssqls2.o
SSQLS3_CXXFLAGS = $(__DEBUGINFO) -Ilib -I/usr/include/mysql \
	-I/usr/include/mysql++ $(CPPFLAGS) $(CXXFLAGS)

SSQLS3_OBJECTS =  \
	ssqls3_ssqls3.o
SSQLS4_CXXFLAGS = $(__DEBUGINFO) -Ilib -I/usr/include/mysql \
	-I/usr/include/mysql++ $(CPPFLAGS) $(CXXFLAGS)

SSQLS4_OBJECTS =  \
	ssqls4_ssqls4.o
SSQLS5_CXXFLAGS = $(__DEBUGINFO) -Ilib -I/usr/include/mysql \

	-I/usr/include/mysql++ $(CPPFLAGS) $(CXXFLAGS)
SSQLS5_OBJECTS =  \
	ssqls5_ssqls5.o
SSQLS6_CXXFLAGS = $(__DEBUGINFO) -Ilib -I/usr/include/mysql \

	-I/usr/include/mysql++ $(CPPFLAGS) $(CXXFLAGS)
SSQLS6_OBJECTS =  \
	ssqls6_ssqls6.o
STORE_IF_CXXFLAGS = $(__DEBUGINFO) -Ilib -I/usr/include/mysql \
	-I/usr/include/mysql++ $(CPPFLAGS) $(CXXFLAGS)
STORE_IF_OBJECTS =  \
	store_if_store_if.o

TQUERY1_CXXFLAGS = $(__DEBUGINFO) -Ilib -I/usr/include/mysql \
	-I/usr/include/mysql++ $(CPPFLAGS) $(CXXFLAGS)
TQUERY1_OBJECTS =  \
	tquery1_tquery1.o
TQUERY2_CXXFLAGS = $(__DEBUGINFO) -Ilib -I/usr/include/mysql \
	-I/usr/include/mysql++ $(CPPFLAGS) $(CXXFLAGS)
TQUERY2_OBJECTS =  \
	tquery2_tquery2.o
TQUERY3_CXXFLAGS = $(__DEBUGINFO) -Ilib -I/usr/include/mysql \
	-I/usr/include/mysql++ $(CPPFLAGS) $(CXXFLAGS)
TQUERY3_OBJECTS =  \
	tquery3_tquery3.o
TQUERY4_CXXFLAGS = $(__DEBUGINFO) -Ilib -I/usr/include/mysql \
	-I/usr/include/mysql++ $(CPPFLAGS) $(CXXFLAGS)
TQUERY4_OBJECTS =  \
	tquery4_tquery4.o
TRANSACTION_CXXFLAGS = $(__DEBUGINFO) -Ilib -I/usr/include/mysql \
	-I/usr/include/mysql++ $(CPPFLAGS) $(CXXFLAGS)
TRANSACTION_OBJECTS =  \
	transaction_transaction.o

### Conditionally set variables: ###

ifeq ($(BUILD),debug)
__DEBUGINFO = -g
endif
ifeq ($(BUILD),release)
__DEBUGINFO = 
endif



### Targets: ###

all: libmysqlpp_ssqls2parse.a ssqlsxlat test_array_index test_cpool test_datetime test_inttypes test_insertpolicy test_manip test_null_comparison test_query_copy test_qssqls test_qstream test_sqlstream test_ssqls2 test_string test_tcp test_uds test_wnp libmysqlpp_excommon.a cgi_jpeg cpool dbinfo deadlock fieldinf for_each load_jpeg multiquery resetdb simple1 simple2 simple3 ssqls1 ssqls2 ssqls3 ssqls4 ssqls5 ssqls6 store_if tquery1 tquery2 tquery3 tquery4 transaction


install: 


uninstall: 


clean: 
	rm -f ./*.o
	rm -f ./*.d
	rm -f libmysqlpp_ssqls2parse.a
	rm -f ssqlsxlat
	rm -f test_array_index
	rm -f test_cpool
	rm -f test_datetime
	rm -f test_inttypes

	rm -f test_insertpolicy
	rm -f test_manip
	rm -f test_null_comparison

	rm -f test_query_copy
	rm -f test_qssqls
	rm -f test_qstream
	rm -f test_sqlstream

	rm -f test_ssqls2
	rm -f test_string
	rm -f test_tcp

	rm -f test_uds
	rm -f test_wnp
	rm -f libmysqlpp_excommon.a
	rm -f cgi_jpeg

	rm -f cpool
	rm -f dbinfo
	rm -f deadlock
	rm -f fieldinf
	rm -f for_each
	rm -f load_jpeg
	rm -f multiquery
	rm -f resetdb

	rm -f simple1
	rm -f simple2
	rm -f simple3
	rm -f ssqls1
	rm -f ssqls2
	rm -f ssqls3
	rm -f ssqls4
	rm -f ssqls5
	rm -f ssqls6
	rm -f store_if
	rm -f tquery1
	rm -f tquery2
	rm -f tquery3
	rm -f tquery4
	rm -f transaction


libmysqlpp_ssqls2parse.a: $(SSQLS2PARSE_OBJECTS)
	rm -f $@
	$(AR) rcu $@ $(SSQLS2PARSE_OBJECTS)
	$(RANLIB) $@

ssqlsxlat: $(SSQLSXLAT_OBJECTS) libmysqlpp_ssqls2parse.a
	$(CXX) -o $@ $(SSQLSXLAT_OBJECTS)   $(__DEBUGINFO) -L. $(LDFLAGS)  -lmysqlpp -lmysqlclient -lmysqlpp_ssqls2parse



test_array_index: $(TEST_ARRAY_INDEX_OBJECTS)
	$(CXX) -o $@ $(TEST_ARRAY_INDEX_OBJECTS)   $(__DEBUGINFO) -L. $(LDFLAGS)  -lmysqlpp -lmysqlclient



test_cpool: $(TEST_CPOOL_OBJECTS)
	$(CXX) -o $@ $(TEST_CPOOL_OBJECTS)   $(__DEBUGINFO) -L. $(LDFLAGS)  -lmysqlpp -lmysqlclient

test_datetime: $(TEST_DATETIME_OBJECTS)
	$(CXX) -o $@ $(TEST_DATETIME_OBJECTS)   $(__DEBUGINFO) -L. $(LDFLAGS)  -lmysqlpp -lmysqlclient


test_inttypes: $(TEST_INTTYPES_OBJECTS)
	$(CXX) -o $@ $(TEST_INTTYPES_OBJECTS)   $(__DEBUGINFO) -L. $(LDFLAGS)  -lmysqlpp -lmysqlclient

test_insertpolicy: $(TEST_INSERTPOLICY_OBJECTS)
	$(CXX) -o $@ $(TEST_INSERTPOLICY_OBJECTS)   $(__DEBUGINFO) -L. $(LDFLAGS)  -lmysqlpp -lmysqlclient

test_manip: $(TEST_MANIP_OBJECTS)
	$(CXX) -o $@ $(TEST_MANIP_OBJECTS)   $(__DEBUGINFO) -L. $(LDFLAGS)  -lmysqlpp -lmysqlclient

test_null_comparison: $(TEST_NULL_COMPARISON_OBJECTS)
	$(CXX) -o $@ $(TEST_NULL_COMPARISON_OBJECTS)   $(__DEBUGINFO) -L. $(LDFLAGS)  -lmysqlpp -lmysqlclient

test_query_copy: $(TEST_QUERY_COPY_OBJECTS)
	$(CXX) -o $@ $(TEST_QUERY_COPY_OBJECTS)   $(__DEBUGINFO) -L. $(LDFLAGS)  -lmysqlpp -lmysqlclient

test_qssqls: $(TEST_QSSQLS_OBJECTS)
	$(CXX) -o $@ $(TEST_QSSQLS_OBJECTS)   $(__DEBUGINFO) -L. $(LDFLAGS)  -lmysqlpp -lmysqlclient

test_qstream: $(TEST_QSTREAM_OBJECTS)
	$(CXX) -o $@ $(TEST_QSTREAM_OBJECTS)   $(__DEBUGINFO) -L. $(LDFLAGS)  -lmysqlpp -lmysqlclient

test_sqlstream: $(TEST_SQLSTREAM_OBJECTS)
	$(CXX) -o $@ $(TEST_SQLSTREAM_OBJECTS)   $(__DEBUGINFO) -L. $(LDFLAGS)  -lmysqlpp -lmysqlclient



test_ssqls2: $(TEST_SSQLS2_OBJECTS) libmysqlpp_ssqls2parse.a
	$(CXX) -o $@ $(TEST_SSQLS2_OBJECTS)   $(__DEBUGINFO) -L. $(LDFLAGS)  -lmysqlpp -lmysqlclient -lmysqlpp_ssqls2parse

test_string: $(TEST_STRING_OBJECTS)
	$(CXX) -o $@ $(TEST_STRING_OBJECTS)   $(__DEBUGINFO) -L. $(LDFLAGS)  -lmysqlpp -lmysqlclient



test_tcp: $(TEST_TCP_OBJECTS)
	$(CXX) -o $@ $(TEST_TCP_OBJECTS)   $(__DEBUGINFO) -L. $(LDFLAGS)  -lmysqlpp -lmysqlclient




test_uds: $(TEST_UDS_OBJECTS)
	$(CXX) -o $@ $(TEST_UDS_OBJECTS)   $(__DEBUGINFO) -L. $(LDFLAGS)  -lmysqlpp -lmysqlclient

test_wnp: $(TEST_WNP_OBJECTS)
	$(CXX) -o $@ $(TEST_WNP_OBJECTS)   $(__DEBUGINFO) -L. $(LDFLAGS)  -lmysqlpp -lmysqlclient


libmysqlpp_excommon.a: $(EXCOMMON_OBJECTS)
	rm -f $@
	$(AR) rcu $@ $(EXCOMMON_OBJECTS)
	$(RANLIB) $@

cgi_jpeg: $(CGI_JPEG_OBJECTS) libmysqlpp_excommon.a
	$(CXX) -o $@ $(CGI_JPEG_OBJECTS)   $(__DEBUGINFO) -L. $(LDFLAGS)  -lmysqlpp_excommon -lmysqlpp -lmysqlclient

cpool: $(CPOOL_OBJECTS) libmysqlpp_excommon.a
	$(CXX) -o $@ $(CPOOL_OBJECTS)   $(__DEBUGINFO) -L. $(LDFLAGS)  -lmysqlpp_excommon -lmysqlpp -lmysqlclient


dbinfo: $(DBINFO_OBJECTS) libmysqlpp_excommon.a
	$(CXX) -o $@ $(DBINFO_OBJECTS)   $(__DEBUGINFO) -L. $(LDFLAGS)  -lmysqlpp_excommon -lmysqlpp -lmysqlclient


deadlock: $(DEADLOCK_OBJECTS) libmysqlpp_excommon.a
	$(CXX) -o $@ $(DEADLOCK_OBJECTS)   $(__DEBUGINFO) -L. $(LDFLAGS)  -lmysqlpp_excommon -lmysqlpp -lmysqlclient

fieldinf: $(FIELDINF_OBJECTS) libmysqlpp_excommon.a
	$(CXX) -o $@ $(FIELDINF_OBJECTS)   $(__DEBUGINFO) -L. $(LDFLAGS)  -lmysqlpp_excommon -lmysqlpp -lmysqlclient

for_each: $(FOR_EACH_OBJECTS) libmysqlpp_excommon.a
	$(CXX) -o $@ $(FOR_EACH_OBJECTS)   $(__DEBUGINFO) -L. $(LDFLAGS)  -lmysqlpp_excommon -lmysqlpp -lmysqlclient

load_jpeg: $(LOAD_JPEG_OBJECTS) libmysqlpp_excommon.a
	$(CXX) -o $@ $(LOAD_JPEG_OBJECTS)   $(__DEBUGINFO) -L. $(LDFLAGS)  -lmysqlpp_excommon -lmysqlpp -lmysqlclient

multiquery: $(MULTIQUERY_OBJECTS) libmysqlpp_excommon.a
	$(CXX) -o $@ $(MULTIQUERY_OBJECTS)   $(__DEBUGINFO) -L. $(LDFLAGS)  -lmysqlpp_excommon -lmysqlpp -lmysqlclient

resetdb: $(RESETDB_OBJECTS) libmysqlpp_excommon.a
	$(CXX) -o $@ $(RESETDB_OBJECTS)   $(__DEBUGINFO) -L. $(LDFLAGS)  -lmysqlpp_excommon -lmysqlpp -lmysqlclient

simple1: $(SIMPLE1_OBJECTS) libmysqlpp_excommon.a
	$(CXX) -o $@ $(SIMPLE1_OBJECTS)   $(__DEBUGINFO) -L. $(LDFLAGS)  -lmysqlpp_excommon -lmysqlpp -lmysqlclient

simple2: $(SIMPLE2_OBJECTS) libmysqlpp_excommon.a
	$(CXX) -o $@ $(SIMPLE2_OBJECTS)   $(__DEBUGINFO) -L. $(LDFLAGS)  -lmysqlpp_excommon -lmysqlpp -lmysqlclient

simple3: $(SIMPLE3_OBJECTS) libmysqlpp_excommon.a
	$(CXX) -o $@ $(SIMPLE3_OBJECTS)   $(__DEBUGINFO) -L. $(LDFLAGS)  -lmysqlpp_excommon -lmysqlpp -lmysqlclient

ssqls1: $(SSQLS1_OBJECTS) libmysqlpp_excommon.a
	$(CXX) -o $@ $(SSQLS1_OBJECTS)   $(__DEBUGINFO) -L. $(LDFLAGS)  -lmysqlpp_excommon -lmysqlpp -lmysqlclient

ssqls2: $(SSQLS2_OBJECTS) libmysqlpp_excommon.a
	$(CXX) -o $@ $(SSQLS2_OBJECTS)   $(__DEBUGINFO) -L. $(LDFLAGS)  -lmysqlpp_excommon -lmysqlpp -lmysqlclient


ssqls3: $(SSQLS3_OBJECTS) libmysqlpp_excommon.a
	$(CXX) -o $@ $(SSQLS3_OBJECTS)   $(__DEBUGINFO) -L. $(LDFLAGS)  -lmysqlpp_excommon -lmysqlpp -lmysqlclient


ssqls4: $(SSQLS4_OBJECTS) libmysqlpp_excommon.a
	$(CXX) -o $@ $(SSQLS4_OBJECTS)   $(__DEBUGINFO) -L. $(LDFLAGS)  -lmysqlpp_excommon -lmysqlpp -lmysqlclient

ssqls5: $(SSQLS5_OBJECTS) libmysqlpp_excommon.a
	$(CXX) -o $@ $(SSQLS5_OBJECTS)   $(__DEBUGINFO) -L. $(LDFLAGS)  -lmysqlpp_excommon -lmysqlpp -lmysqlclient



ssqls6: $(SSQLS6_OBJECTS) libmysqlpp_excommon.a
	$(CXX) -o $@ $(SSQLS6_OBJECTS)   $(__DEBUGINFO) -L. $(LDFLAGS)  -lmysqlpp_excommon -lmysqlpp -lmysqlclient


store_if: $(STORE_IF_OBJECTS) libmysqlpp_excommon.a
	$(CXX) -o $@ $(STORE_IF_OBJECTS)   $(__DEBUGINFO) -L. $(LDFLAGS)  -lmysqlpp_excommon -lmysqlpp -lmysqlclient

tquery1: $(TQUERY1_OBJECTS) libmysqlpp_excommon.a
	$(CXX) -o $@ $(TQUERY1_OBJECTS)   $(__DEBUGINFO) -L. $(LDFLAGS)  -lmysqlpp_excommon -lmysqlpp -lmysqlclient



tquery2: $(TQUERY2_OBJECTS) libmysqlpp_excommon.a
	$(CXX) -o $@ $(TQUERY2_OBJECTS)   $(__DEBUGINFO) -L. $(LDFLAGS)  -lmysqlpp_excommon -lmysqlpp -lmysqlclient


tquery3: $(TQUERY3_OBJECTS) libmysqlpp_excommon.a
	$(CXX) -o $@ $(TQUERY3_OBJECTS)   $(__DEBUGINFO) -L. $(LDFLAGS)  -lmysqlpp_excommon -lmysqlpp -lmysqlclient

tquery4: $(TQUERY4_OBJECTS) libmysqlpp_excommon.a
	$(CXX) -o $@ $(TQUERY4_OBJECTS)   $(__DEBUGINFO) -L. $(LDFLAGS)  -lmysqlpp_excommon -lmysqlpp -lmysqlclient



transaction: $(TRANSACTION_OBJECTS) libmysqlpp_excommon.a
	$(CXX) -o $@ $(TRANSACTION_OBJECTS)   $(__DEBUGINFO) -L. $(LDFLAGS)  -lmysqlpp_excommon -lmysqlpp -lmysqlclient

ssqls2parse_parsev2.o: ./ssx/parsev2.cpp
	$(CXX) -c -o $@ $(SSQLS2PARSE_CXXFLAGS) $(CPPDEPS) $<

ssqlsxlat_genv2.o: ./ssx/genv2.cpp
	$(CXX) -c -o $@ $(SSQLSXLAT_CXXFLAGS) $(CPPDEPS) $<

ssqlsxlat_main.o: ./ssx/main.cpp
	$(CXX) -c -o $@ $(SSQLSXLAT_CXXFLAGS) $(CPPDEPS) $<


test_array_index_array_index.o: ./test/array_index.cpp
	$(CXX) -c -o $@ $(TEST_ARRAY_INDEX_CXXFLAGS) $(CPPDEPS) $<


test_cpool_cpool.o: ./test/cpool.cpp
	$(CXX) -c -o $@ $(TEST_CPOOL_CXXFLAGS) $(CPPDEPS) $<

test_datetime_datetime.o: ./test/datetime.cpp
	$(CXX) -c -o $@ $(TEST_DATETIME_CXXFLAGS) $(CPPDEPS) $<



test_inttypes_inttypes.o: ./test/inttypes.cpp
	$(CXX) -c -o $@ $(TEST_INTTYPES_CXXFLAGS) $(CPPDEPS) $<


test_insertpolicy_insertpolicy.o: ./test/insertpolicy.cpp
	$(CXX) -c -o $@ $(TEST_INSERTPOLICY_CXXFLAGS) $(CPPDEPS) $<

test_manip_manip.o: ./test/manip.cpp
	$(CXX) -c -o $@ $(TEST_MANIP_CXXFLAGS) $(CPPDEPS) $<



test_null_comparison_null_comparison.o: ./test/null_comparison.cpp
	$(CXX) -c -o $@ $(TEST_NULL_COMPARISON_CXXFLAGS) $(CPPDEPS) $<


test_query_copy_query_copy.o: ./test/query_copy.cpp
	$(CXX) -c -o $@ $(TEST_QUERY_COPY_CXXFLAGS) $(CPPDEPS) $<

test_qssqls_qssqls.o: ./test/qssqls.cpp
	$(CXX) -c -o $@ $(TEST_QSSQLS_CXXFLAGS) $(CPPDEPS) $<

test_qstream_qstream.o: ./test/qstream.cpp
	$(CXX) -c -o $@ $(TEST_QSTREAM_CXXFLAGS) $(CPPDEPS) $<

test_sqlstream_sqlstream.o: ./test/sqlstream.cpp
	$(CXX) -c -o $@ $(TEST_SQLSTREAM_CXXFLAGS) $(CPPDEPS) $<

test_ssqls2_ssqls2.o: ./test/ssqls2.cpp
	$(CXX) -c -o $@ $(TEST_SSQLS2_CXXFLAGS) $(CPPDEPS) $<


test_string_string.o: ./test/string.cpp
	$(CXX) -c -o $@ $(TEST_STRING_CXXFLAGS) $(CPPDEPS) $<

test_tcp_tcp.o: ./test/tcp.cpp
	$(CXX) -c -o $@ $(TEST_TCP_CXXFLAGS) $(CPPDEPS) $<



test_uds_uds.o: ./test/uds.cpp
	$(CXX) -c -o $@ $(TEST_UDS_CXXFLAGS) $(CPPDEPS) $<


test_wnp_wnp.o: ./test/wnp.cpp
	$(CXX) -c -o $@ $(TEST_WNP_CXXFLAGS) $(CPPDEPS) $<

excommon_printdata.o: ./examples/printdata.cpp
	$(CXX) -c -o $@ $(EXCOMMON_CXXFLAGS) $(CPPDEPS) $<



cgi_jpeg_cgi_jpeg.o: ./examples/cgi_jpeg.cpp
	$(CXX) -c -o $@ $(CGI_JPEG_CXXFLAGS) $(CPPDEPS) $<


cpool_cpool.o: ./examples/cpool.cpp
	$(CXX) -c -o $@ $(CPOOL_CXXFLAGS) $(CPPDEPS) $<

dbinfo_dbinfo.o: ./examples/dbinfo.cpp
	$(CXX) -c -o $@ $(DBINFO_CXXFLAGS) $(CPPDEPS) $<

deadlock_deadlock.o: ./examples/deadlock.cpp
	$(CXX) -c -o $@ $(DEADLOCK_CXXFLAGS) $(CPPDEPS) $<

fieldinf_fieldinf.o: ./examples/fieldinf.cpp
	$(CXX) -c -o $@ $(FIELDINF_CXXFLAGS) $(CPPDEPS) $<

for_each_for_each.o: ./examples/for_each.cpp
	$(CXX) -c -o $@ $(FOR_EACH_CXXFLAGS) $(CPPDEPS) $<

load_jpeg_load_jpeg.o: ./examples/load_jpeg.cpp
	$(CXX) -c -o $@ $(LOAD_JPEG_CXXFLAGS) $(CPPDEPS) $<

multiquery_multiquery.o: ./examples/multiquery.cpp
	$(CXX) -c -o $@ $(MULTIQUERY_CXXFLAGS) $(CPPDEPS) $<

resetdb_resetdb.o: ./examples/resetdb.cpp
	$(CXX) -c -o $@ $(RESETDB_CXXFLAGS) $(CPPDEPS) $<

simple1_simple1.o: ./examples/simple1.cpp
	$(CXX) -c -o $@ $(SIMPLE1_CXXFLAGS) $(CPPDEPS) $<

simple2_simple2.o: ./examples/simple2.cpp
	$(CXX) -c -o $@ $(SIMPLE2_CXXFLAGS) $(CPPDEPS) $<

simple3_simple3.o: ./examples/simple3.cpp
	$(CXX) -c -o $@ $(SIMPLE3_CXXFLAGS) $(CPPDEPS) $<



ssqls1_ssqls1.o: ./examples/ssqls1.cpp
	$(CXX) -c -o $@ $(SSQLS1_CXXFLAGS) $(CPPDEPS) $<


ssqls2_ssqls2.o: ./examples/ssqls2.cpp
	$(CXX) -c -o $@ $(SSQLS2_CXXFLAGS) $(CPPDEPS) $<

ssqls3_ssqls3.o: ./examples/ssqls3.cpp
	$(CXX) -c -o $@ $(SSQLS3_CXXFLAGS) $(CPPDEPS) $<

ssqls4_ssqls4.o: ./examples/ssqls4.cpp
	$(CXX) -c -o $@ $(SSQLS4_CXXFLAGS) $(CPPDEPS) $<

ssqls5_ssqls5.o: ./examples/ssqls5.cpp
	$(CXX) -c -o $@ $(SSQLS5_CXXFLAGS) $(CPPDEPS) $<

ssqls6_ssqls6.o: ./examples/ssqls6.cpp
	$(CXX) -c -o $@ $(SSQLS6_CXXFLAGS) $(CPPDEPS) $<


store_if_store_if.o: ./examples/store_if.cpp
	$(CXX) -c -o $@ $(STORE_IF_CXXFLAGS) $(CPPDEPS) $<

tquery1_tquery1.o: ./examples/tquery1.cpp
	$(CXX) -c -o $@ $(TQUERY1_CXXFLAGS) $(CPPDEPS) $<




tquery2_tquery2.o: ./examples/tquery2.cpp
	$(CXX) -c -o $@ $(TQUERY2_CXXFLAGS) $(CPPDEPS) $<


tquery3_tquery3.o: ./examples/tquery3.cpp
	$(CXX) -c -o $@ $(TQUERY3_CXXFLAGS) $(CPPDEPS) $<

tquery4_tquery4.o: ./examples/tquery4.cpp
	$(CXX) -c -o $@ $(TQUERY4_CXXFLAGS) $(CPPDEPS) $<



transaction_transaction.o: ./examples/transaction.cpp
	$(CXX) -c -o $@ $(TRANSACTION_CXXFLAGS) $(CPPDEPS) $<

.PHONY: all install uninstall clean



# Dependencies tracking:
-include ./*.d

Changes to lib/transaction.cpp.

1

2
3
4
5
6
7

8
9
10
11
12
13














14
15
16
17
18
19
20
21
22
23

24
25
26


27











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
56
57
58
59

60
61
62
63
64
65
66
67
68
69
70

71









72
73
74
75
76
77
78
79

80
81
82
83
84
85
86

87











88






89
90
91
92
93
94
95
96
97
98
99
100
101



102












103
104
105
106

107
108
109
110
111

112
113
114
115
116

117
118
119
120
121









/***********************************************************************

 transaction.cpp - Implements the Transaction class.

 Copyright © 2006-2014 by Educational Technology Resources, Inc.
 Others may also hold copyrights on code in this file.  See the
 CREDITS.txt file in the top directory of the distribution for details.


 This file is part of MySQL++.

 MySQL++ is free software; you can redistribute it and/or modify it
 under the terms of the GNU Lesser General Public License as published
 by the Free Software Foundation; either version 2.1 of the License, or
 (at your option) any later version.















 MySQL++ is distributed in the hope that it will be useful, but WITHOUT
 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
 License for more details.

 You should have received a copy of the GNU Lesser General Public
 License along with MySQL++; if not, write to the Free Software
 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
 USA

***********************************************************************/

#define MYSQLPP_NOT_HEADER


#include "common.h"












#include "transaction.h"

#include "connection.h"
#include "query.h"

using namespace std;
using namespace mysqlpp;


//// ctors /////////////////////////////////////////////////////////////

















Transaction::Transaction(Connection& conn, bool consistent) :
conn_(conn),
finished_(true)		// don't bother rolling it back if ctor fails
{

	// Begin the transaction set
	Query q(conn_.query("START TRANSACTION"));
	if (consistent) {
		q << " WITH CONSISTENT SNAPSHOT";
	}
	q.execute();

	// Setup succeeded, so mark our transaction as not-finished.




	finished_ = false;
}














Transaction::Transaction(Connection& conn, IsolationLevel level,
		IsolationScope scope, bool consistent) :
conn_(conn),
finished_(true)		// don't bother rolling it back if ctor fails
{

	// Set the transaction isolation level and scope as the user wishes
	Query q(conn_.query("SET "));
	if (scope == session) q << "SESSION ";
	if (scope == global)  q << "GLOBAL ";
	q << "TRANSACTION ISOLATION LEVEL ";
	switch (level) {
		case read_uncommitted:	q << "READ UNCOMMITTED"; break;
		case read_committed:	q << "READ COMMITTED";   break;
		case repeatable_read:	q << "REPEATABLE READ";  break;
		case serializable:		q << "SERIALIZABLE";     break;
	}

	q.execute();










	// Begin the transaction set.  Note that the above isn't part of
	// the transaction, on purpose, so that scope == transaction affects
	// *this* transaction, not the next one.
	q << "START TRANSACTION";
	if (consistent) {
		q << " WITH CONSISTENT SNAPSHOT";
	}

	q.execute();

	// Setup succeeded, so mark our transaction as not-finished.
	finished_ = false;
}



//// dtor //////////////////////////////////////////////////////////////


















Transaction::~Transaction()
{
	if (!finished_) {
		try {
			rollback();
		}
		catch (...) {
			// eat all exceptions
		}
	}
}





//// commit ////////////////////////////////////////////////////////////













void
Transaction::commit()
{

	conn_.query("COMMIT").execute();
	finished_ = true;
}



//// rollback //////////////////////////////////////////////////////////

void
Transaction::rollback()
{

	conn_.query("ROLLBACK").execute();
	finished_ = true;
}











<
>
|
|
|
<
|
|
>
|
|
|
|
|
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
|
|
|
|
|
|
|
|
<
>
|
|
|
>
>
|
>
>
>
>
>
>
>
>
>
>
>
|
|
|
|
|
|
|
|
|
|
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
|
|
|
<
>
|
|
<
<
<
<
|
|
>
>
>
>
|
<
>
>
>
>
>
>
>
>
>
>
>
>
>
|
|
|
|
|
<
>
|
|
|
|
|
|
|
|
|
|
<
>
|
>
>
>
>
>
>
>
>
>
|
|
|
|
|
|
|
<
>
|
|
|
|
<
|
|
>
|
>
>
>
>
>
>
>
>
>
>
>
|
>
>
>
>
>
>
|
<
<
<
<
<
<
|
<
<
<
|
|
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
|
|
|
<
>
|
|
<
|
|
>
|
|
|
|
<
>
|
|
<
|
|
>
>
>
>
>
>
>
>
>

1
2
3
4

5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
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
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85

86
87
88




89
90
91
92
93
94
95

96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113

114
115
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
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
191
192

193
194
195

196
197
198
199
200
201
202

203
204
205

206
207
208
209
210
211
212
213
214
215
216

C Version\s3.1.0
D 2010-06-03T17:59:22.000
F Bakefiles.bkgen b7f974c77ceafc564c3c9273532f85ff1284f26973ae7492c16180b88e84ee2b
F COPYING.txt c943babbd1de963894a9ba8583e8f50cdc7a6ab7c0522a0251c8cd21caa9f672

F CREDITS.txt 29322dd9f76ac03c4c0601bd14772112eac1a4fdb1b44014ecc1a3ca3a74fec9
F ChangeLog 7335c489cfdeeb43fd4e23c292a82c6ba79f3c5c04099d4add937d21f61412d4
F HACKERS.txt 6f1c4cfc77b41d80064c819f28eb77e732e7a9c3d0cee5bd64d8dd08b757b84c
F INSTALL.txt 34f34084bb61b1092c2baaba90fb48723010dbe50d09acb5b170820aafad41b5
F LICENSE.txt 97ebb45ce18ea0be5a31a8aec2228eee997e3ed3df0aa31771ade1999d483a82
F Makefile.mingw 2c0ffee8dafb31da79339bd0cf761f6a5e541f47d5d3c525615ad53091e2dffa
F Makefile.simple 320dc14eb03b73153e3a61999ac87f4baa6a88bd5fa760c6ce04c11d3bd03c54
F README-Cygwin.txt fb25857013841a657741c323acb61cdf4f168efaeff705d2e5973b79f5eb960b
F README-Linux.txt 418e01796ed0bc9b54ac87aaf2d38da33845e26c10fb04e77a9e10ad2ee01fb2
F README-Mac-OS-X.txt e8bd6329fa524099e0e2ca7fc3e4576a0b0c1b7a6ce3fa562a144cce92f68d67
F README-MinGW.txt e704c7fbc381c893fa654fa894657a45bfff7b00655221b3ab43b055774e0363
F README-Solaris.txt 17bab66b3620f84a1b18c99a88abf447d46ad915888485e8dc4ee6a3c7898c9e
F README-Unix.txt eba661f1ff35efbf8161e9f2e5a7a997eb1c300319776dd22027382e133777f1
F README-Visual-C++.txt 7b86c401b66d68a36569dd4bf34409232882debb482823d1e0e0c9e0d47378f8
F README-examples.txt 1e9e6a1f8602029653bc44120a36c1e50fe583b5489639081f745255f18400a3
F README.txt beb3b1247585cc45b04d82a823dd81d43f81ff6e8a468d956d3a5d5b42fe93dd
F Wishlist 20b86a9fdcc8ab6caba2d58f4f93045692101baa5ff0a71863cf29143d8d4978
F bk-deps 11c17ee77c90bf128e924b6cbd4b7375aa4474f99f8065b4d15fb26980f4c5e0 x
F bmark.txt 973d955a0625b12f5f9045fb31b818c0d24a17926320c3e2a1a94e3d2f778c39
F bootstrap 2643a52ec57f419d252589082582db59b4a501f08d1228b7a28b862867c7711e x
F bootstrap.bat 8c501dacd4993d4bdf43a67f1c6645b22c85fb03f36b423600a2a68c36ce75d2
F cleanmf e385426a032ada497be42ff7504ef1fffcccd34635af530c25f19e2f209ec653 x
F config.h.in aa61e9a50ba0e3708e32787cae2f540330cf3cf617992b65c42736b51be2f7a0
F config/acx_pthread.m4 8a9dbf4783b282f82c062edac20886e75e0ef9d555ac59b0dad68f1559a3a460
F config/autoconf_inc.m4 eb7644652e7cb0054cd952d1b190c87ccb741d286e6c169c68f793fba181c3f8
F config/libm.m4 de3dcf0b6e8149f13c9e26dcdeaf25bf5b40fa3993546835b29c0a3be6ee63ea
F config/localtime_r.m4 8ba2bda9bdf152d8f901180b2eec716f75c381c5ed2d98666f4f0cfe29152256
F config/mysql++.m4 a305b5d0f8c47b51e487381ef4e38f4acc63683b2d10c9c15065430044e4d207
F config/mysql_loc.m4 b8b47767ca53e976578d4dcac16493cdd06a511c48cd6a7f2e12c012d51cf696
F config/mysql_ssl.m4 82d5c48515915eec8c2c817216a31b1f5a167382b150e547a306e5715905ce57
F config/socket_nsl.m4 6dd364d066feec0abf2b2bcdd377710010c459d3c6fbedad77a20f38997c7de2
F config/stl_slist.m4 614e5c3929b7b506b1f61ce6a4f089a5ef5acc049a0920963a32dd2bd11ad7c1

F configure.ac 1978fb7f73d9e72bb641b275f9701e402290f48882db6e89655b7e6903bb1d2d
F doc/README-devel-RPM.txt d920bb8de3af6578f5cbe1d41b53010b3e0c37163ec8226aa708d1aab869ec83
F doc/README-manuals-RPM.txt 12316b39e05f17d22d378647a574c7f6d1a12bca86ca75c54e761555b9f34763
F doc/ssqls-pretty d5f23af891a27583871e0bc1dd3c3df1f43eb6ce02e8ba06f69c3b5a82efedc5 x
F doc/userman/Makefile 3741a189535fc84855d8452d0154dbc9ccedbbc0c21a3c6f51a39aeff773b483
F doc/userman/breakages.dbx 0877f7cb8863a6eb4f0131a3c4be5d60bfbf603c0abdd8b73ddff14edf14d218
F doc/userman/common.xsl ec35926ab1e3a6c06d2df9ddd383e6d6cc2736db2385b193d08802d9190d58ee
F doc/userman/configuration.dbx d2dfdd9570d62eed00c47c5fbf0fbc156fbb5245d8cfa1ce6cd6e0a7212b2469
F doc/userman/fo.xsl ac5397b661eb25507f9709f3e420b0d6be899d5bbed5c2cbff5c76b1a09ceadc
F doc/userman/html.xsl acaffa4de9387b095cb9bc22508d5bebfeccb5c4c506bb067ca0dc881536b554
F doc/userman/incorporating.dbx 52b2e4f8853fc3cbfc18fc0ec1710886ff687e0db89a275527b6e588434c491e
F doc/userman/intro.dbx a4d316be95d82256f9ba8ee6d725f3d07c6d68d7c66a3f6e21a0d02ff17e2732
F doc/userman/licenses.dbx 9cbaec5d5d90c5af2f2ee9c9f15f022a7011508741c4feaf3f0f3fe8f1bb5fac
F doc/userman/mktxt d7fb06e2c293cb0106ec5ba5508757022740f07e79f96065925735fa11506374 x
F doc/userman/overview.dbx 6ceb7c85beab820f19c8c7ff1f42b542eeece43909aa0bbc3ca74df50ed1b44a
F doc/userman/section-template.dbx 258801d08cb6774a5063c2f92cfaec176712cf47f68641bf724e4a944c02c70a
F doc/userman/ssqls.dbx f4bb6f36e0725fe5062a0a8b8af16a0fe62a9800a242dfd4339844b942b23106
F doc/userman/threads.dbx 82addab7e8625172f4ddfa5ea9318ac124ad63bc8f869732a7695cc492b7a8ca
F doc/userman/tquery.dbx 13530007922f624dce13610e930cf9612966575ecb52ad578ba7cc410611c22e
F doc/userman/tutorial.dbx 0ae1c2a634cabe822d4ef3b8259b1f9968f7c77bf32e9ebfb0293a8b057f58be
F doc/userman/unicode.dbx 012d380d8bd1c83f21aba11d66c8bc8e7cca19f28b63f3e14f382f678277f4ce
F doc/userman/userman.dbx b47da885c70d4eed421104c5d08d041ba7087a31f7d8212fab72ae071eed6383
F doc/userman/userman.dbx.in ec604d72ffd8c184e934cd2033036d102c6d35ae097e585ee13995e99a199842
F dtest 257ddf48697e9841107610031187e5c9676118fac4ba3de9e753140f91056001 x
F examples/cgi_jpeg.cpp 41c856cdd9a4c36f2130e08b11fae4a4983cf747282a50cbab99006d0bc1f5b1
F examples/cpool.cpp e695c44737d7b68dd6cfd562a8e82cddaf2a835b314d81b0fafec2ff29bc1858
F examples/dbinfo.cpp 9c73702befdd5ba82364634d47fefad8ef164d54dff80fce5bd6d2d67af70a1d
F examples/deadlock.cpp e2d48b901cb0c9ef8e2e18050754f874489fa76eb944b55e8120211ba5afbdd7
F examples/fieldinf.cpp b92f510ca75e331f27913c3da776f7dc4ea5e6a17e0ac9d39beb1b89806f2c3b
F examples/for_each.cpp 3efb48e69dc820480f465c4af927e12937b0df6e3345ea7ede39a22a3f34d2ff
F examples/images.h eff98d54763fcdc1ab8e58ab71648f74554d192b9d7bf99b93669de65e70fa30
F examples/load_jpeg.cpp 5259990f5295ef68299d39d229076fa6835d8eed9c050137e9b09bad4a142886
F examples/logo.jpg b551f2a4609684c83c17acc32faa08af659df397aba70fe7e0f12de82c4bc934
F examples/multiquery.cpp 742d8707efdf9b1a8c0c531a6f81e2b324e9745fbbd9565e53f5d2dec2507a9c
F examples/printdata.cpp cabfdb65b121a0ada9cdd67379d458b8b77eb69d60a44a369c73dfa036700fc9
F examples/printdata.h 201ba1d04b99ef5db9d69d99f985d41fab983a12810c4e16b9a433287c92b483
F examples/resetdb.cpp 758eaab06a2daf476205ec14e9f957aa178bcf91dfe425ff56e8dd7f8fcb0a67
F examples/simple1.cpp 8140c09587cebe3d8f97ae0dafe29188b5578d26d58adeb7c81e1f5faceb9a4b
F examples/simple2.cpp e4edb4d49033848ee82c54d5b6d46f3318bf44c56d5959719ab6f7eaa7f0da60
F examples/simple3.cpp 604fa7b0dc9b1f7677a7088493b8fa25014bc38f42f79f9002f95c63967c3389
F examples/ssqls1.cpp 26c1a1af36aebcfc6a0adeaedddbc3eb9bbd302933cdb50a5dc275146f03233a
F examples/ssqls2.cpp faead49be3a339b0817fa74b77f16240895cfa4ebbe85f067ad721e4b0475d61
F examples/ssqls3.cpp 5f776cd5de0a9e1b79b4431f66c89dabe26f52a205f0580a60703ce771c14a61
F examples/ssqls4.cpp 4a0ba3becc091fac4003ff905daef1f6644cc9e992b6714e525ac50ccaf472b9
F examples/ssqls5.cpp ed53e908e3206d61081485c8ac327abc237316240f047a91415a69a71bcd2e69
F examples/ssqls6.cpp 71a4d0b2256e288318dc460ba72e46a97c883451269148dc130757bd1f8cb886
F examples/stock.h 7a27e43688f7fb40e19ee36ae6637ad93aca88f4d72a45cc4fea06ffbcd77f1e
F examples/store_if.cpp 0adea2de699079171e50d65e77c67d768d0f0face939b59146e220a442d80358
F examples/threads.h 78091cf6989ba263082a8aade1b1fa1d64130f5e2d5e353e5afcbe7c6bb4fbed

F examples/tquery1.cpp 6c6965a13411541a923f44e69f442a53aadac50c49192963fb982c3aeeada802
F examples/tquery2.cpp 96a2a408d852707bcbd7f14cfa823fb8331763ac752b445e4f5acfc3bd3fb94e
F examples/tquery3.cpp e0e53072caeffe9e3944a3bbff081cc2751fe9342e15eb98168ef17fcfe686f7




F examples/tquery4.cpp 753892f736a61afa926cdb1eab7a34c1ebd6f4b5dcbb39b21aaafe50bed1c909
F examples/transaction.cpp d1b310ebbea4cfe14f7c8656db8485b8ab6416eb9912f7911001fad02db25d4e
F examples/vstudio/mfc/mfc.cpp 81bc84b78340d7e4fba2c850f4b25720ad7fcfb4d58fefe1cce3c3ed9bd2e019
F examples/vstudio/mfc/mfc.h e1da8ccc157701e5c208cf8b24b51cf08d8f13b48a8809d8223318ad813991ab
F examples/vstudio/mfc/mfc.rc 7f893118cb86cbcbf8a4d4d30fd5f122d7b7916895aba82327c770354dbd842a
F examples/vstudio/mfc/mfc_dlg.cpp 5b2eb625d7fb07648b9a0429490a0812b186e237b2cd690025f01483356cdaad
F examples/vstudio/mfc/mfc_dlg.h eb5ba79ffe166455e27601b94642566de7822a87329661abac15f4e200f7bb72

F examples/vstudio/mfc/resource.h ca71f958b51bf17dfbba0d1591211efe36187ef869b6bff5e0dc9a59cf40a2f6
F examples/vstudio/mfc/stdafx.h b5a1c41c2a252ab4275ec9d8a584f058c4596c2c6d767ee756a4f4546ea86fd1
F examples/vstudio/wforms/AssemblyInfo.cpp 08e3cfc50233132ea5d4b70b47fa2bce669c2c6a97896f8b0ec62b882e1deeb1
F examples/vstudio/wforms/MainForm.h 0f3c1f1f59d50683e262a07c2db28b2eba3dbcdc23f190354b18f7b41444781f
F examples/vstudio/wforms/MainForm.resX f69089f338845d493eccdd05a2650a7f3cca9f0993f746723d7f7d08054d681f
F examples/vstudio/wforms/resource.h 3c4a478a4643ae9ccf7988df1613197a7f4ab3483455c8037004c6da26b036e9
F examples/vstudio/wforms/wforms.cpp 6566a4a77faae13ee3bdd474c347a62e68632c5f6b053194aa40d12689e4a160
F exrun 4450f57cd0ed563925652e0fc3af646a0fa471138831c1e120ec534aa65dd948 x
F exrun.bat f1884f9c023c322373f814e7d70f6488771569f4035c7d1697d970b7bb9e893d x
F install.hta.in c154df770e08f8b617f9aed85dbfe54e2650e64ab63f6afb791a3a00829ed678
F lib/Doxyfile.in 28f952ba31b1dbd9af3754b4b0972225429e30fa22417d6cc5b7d4fd769f81e9
F lib/autoflag.h 58f79df863e952a15542a0001a87a037af86b9014bc3787f99489a404f502957
F lib/beemutex.cpp 729da280560845acae28d48d5c01455713ef87c358637279600dc254442c19fc
F lib/beemutex.h a88f946fecfdf1f998a3fa1c33764cd8001e45fe17ee8c2db0cdc38dad54e4d7
F lib/cmdline.cpp 3cda94669e4c11b977f94c7b8a1a8b9d3b9e677a11167b4fe4d639d2a24a713e
F lib/cmdline.h 53678455c3bb2de7a6af5b89d539e5895ee99649a6183340778b8bbd9cbfe794
F lib/common.h 870e62ebff29f43e0f27030c433c6e7dcc8b42f079f8012b2987a00976aafd01
F lib/comparable.h 4abef254c194319823ad527991d2f1065f24fc435439469e2c7795c8ba563471

F lib/connection.cpp f3c0a4823a619d0722de585f96548e9d8aa3f9d0de9a88604e5f8b6bcf63ffde
F lib/connection.h b76a8d178d4f1f730a9cab645112fcbfbba80c50e2bc2eca671527809febea18
F lib/cpool.cpp c7e9798763fb203a2a2b662371b5cd1f9a356551866f1f6f83c662bd5a4038d1
F lib/cpool.h 0f199b2b65847bb3b5e85388b505d3b6d1d0a16069256db3b6f46ea6f676f3f0
F lib/datetime.cpp efcef86ddea19a3d99db91df4d9816e5cd0cc6d044ecb774a41f8738006a5dfb
F lib/datetime.h 3a5f9ec152eace11864527c907bf8f9543bb96a939fb1f23a129133432ade11f
F lib/dbdriver.cpp 2b99a8b806cc5ffacf12e12df69bb526676d3a21e737b0fe98927383f33f840b
F lib/dbdriver.h 1feb93357f4c756c851c9300c45795ecdc6c52ab3c3853277a625ce32a5c604e
F lib/exceptions.h 45fc9a816fd4222661dce0b8f2649be7a9c22fdd9427e54dd8fd9b355939a53a
F lib/field.h 0e52ca8dc9377690ca6f0ae8a70a0840ddaa9132eba233ea1f558a00a74b748d
F lib/field_names.cpp 5b07458d72e3b75703dc0a499be7788470c1999fd66bd979d7c05a6a1b078e00

F lib/field_names.h 0291d3307f2b96f3a71dfb0ebaa14598f3152a48bfbb9eaab798bbe4e7700182
F lib/field_types.cpp f398720812c018c158c218a6e22959c908973ede7231dcb76b7bede546b8b16d
F lib/field_types.h f42e8d92974d7043b5f82e7c6f9772f0a05e61bfba7fa7761a2427c306beea18
F lib/insertpolicy.h af2681726f5119025fbb1056fcf0a30b26bfd638763cf29a236b90b7580187fc
F lib/manip.cpp 9dc4486fde9f360bcf05497bfca1dc95ad7d2367c5806240dfd76f48d2af56a8
F lib/manip.h ec92e560792a7ae7418e6f766fc2ca70efb6d6c2892707bf1c2fa152e4e8c370
F lib/myset.cpp 462c808158c304a45340a3bcb04bbfe25ecc36103ad2b88812f2efe7b1cd9f00
F lib/myset.h 24521ab1b8db1aa23215d8f7132235107921ff5f97998139080325518c49a9b1
F lib/mysql++.cpp b6a0f2325a8c5fa6d3483c95ff64130de75b82ae090505ccb6a434d9332553f1
F lib/mysql++.h.in dac79a2f0ea62f3d5e6b965243b5aed928c5c067daace3ff04c442d44fb2aae4
F lib/mystring.cpp 91086ed3a3bd79e622c3de4c440f5e83260147b7c4ea641bfdbb3a0001bce2d2
F lib/mystring.h 73a5dcf949b42550ac639ff2d846826ef53634d73238f7caa696242ef035eb46
F lib/noexceptions.h 90b154a5656a36c65a598a6907dcf70478517b8d7aa1ab5747d034146e764ba8
F lib/null.cpp 29054e85daa1a2df68d638c5745924906e8479344e057f8b1f8a151b3ced7fd9
F lib/null.h 885bb0030775f0abf6e3ea62975d5e80b14b3774290466b8bc6c0475e15d945b
F lib/options.cpp 0e19d7f530501f79c747c6a60f7d8f4e53fc1f17474da38e50a6794608346c99
F lib/options.h e426a7427be8fd7ece43c1a2a23704388cbff8cac998742d67bd7d3f6a5e9864
F lib/qparms.cpp c3c7ece6a8cf4381813feb977ccd21cf076aec1af0b5056b0b2bbb12c1cfdb40

F lib/qparms.h 79db4335641deba0db8f107584357de812eb34554054572a5a3b0eb3288e7a28
F lib/query.cpp 2a7e4b1f2d746973b2fcb18c7be86dceb564f48ec16cf465cf851658cb4e5bee
F lib/query.h 7dfa247eecebf8512fd9fcc1583fabf03042f559cd619ecd7b7de3ae3a221000
F lib/querydef.h a42f3204b27062fd462b4f4edca9f904e89b01310a4683b194ca4720f0994771
F lib/querydef.pl b79a8d4d97fe46bd5aecfc01a3247723a406c5a5ec3f97467b900aee32c2c60b x

F lib/refcounted.h ba5b22879ef5422ece2344d769f46343c86f8717d273025fc30b8cef9d40fbb7
F lib/result.cpp c607b01012068721ef1a9368de745823f161c1c54269d89c45f13bcbaa9edfcd
F lib/result.h 45a3d9569eea39511ffb851e16dc42d2c2e19ccc800d49659cb2511bb77f6cad
F lib/row.cpp 4ba4e766292db1bdcee4900b1af50d2f651bae82513e5d9eb482383333e9d6df
F lib/row.h c5b3593b15455839b8cb834ba35f6191927122400b410896f237aceceb99b286
F lib/scopedconnection.cpp 6df0bc476d007b09774d7dbb40cfaf1fd4c573d74c4a34ef30a3c1a777e4a9e9
F lib/scopedconnection.h 146a49b448e61c0cbc4ef86b11160830b5df42fd1c9e3c0c5f1191199ef734d0
F lib/sql_buffer.cpp be96654c01d929005c17e934a12d1b9f20ae25c4badd86816370f60000c77ecf
F lib/sql_buffer.h 68c0b526af54a2eb3e17b68aeeebde1d525360068992ba28b6620ce5691dedf8
F lib/sql_types.h e121e529fce8e070a476d79e83d5dfa3049bf48718b38e3a68d179df84c86159
F lib/sqlstream.cpp 991164b05a878f4ee3d1baa426d9051e9867ec5d2621515ba57e529a5b75b943
F lib/sqlstream.h a4734317d1215fe89fda7c98db76bfc17219538af03d817d39d777ee24e90d84
F lib/ssqls.h 0f729f497cb5b8c5750badd2d8076072bc98231923e26285a6713c15e354e15e
F lib/ssqls.pl d41c988aef33aebe5bd96ff921f27c389c88fdf52ea63fc6b2f874e84638caac x
F lib/ssqls2.cpp dc09245b78971a66cc6355a97fe94452069727521b220cd06565b8509394867f
F lib/ssqls2.h aed72d98f892b9ab4794e7a74eb0499a1e8ee81e1be1bf6e8eee3712c751d923
F lib/stadapter.cpp 293aa63a38226de8bf141756f6ef03bace592b3636f2b1b75522b69b2dafa7fe
F lib/stadapter.h c4d6a12f569e7999d121831fa80d3639b7502f640cc9d4562a98eef443f400cb
F lib/stream2string.h 602da8de8b7273ac144bca3e120982754071ec64e43003f512931e206cf5f536
F lib/tcp_connection.cpp e2b1a929088f62d8ad8ab79561356c3d30b0e8a5a0cf4d529231f3669a67b8b7
F lib/tcp_connection.h e1faf059e010075cf7f7ddbe51f2a6fb7558ee2ea5ee7c3da6599d7fa00a3cbb
F lib/tiny_int.h 93e87d50703c4871eb237bf88918ad0a7147c4f4abc7f3475c07fd4b2817825c
F lib/transaction.cpp 02c4297cac22932c6dcbb53e128293077c5757dfaee68f4bf116905d5d8dee86






F lib/transaction.h fcfcbfdc2784cd7865da4ecb5599ba2d81a3d8b0d3b20fde3d622fdcd57e5496



F lib/type_info.cpp 826bb3e62ce7d6901094d74c76d538ceedb68220ddd58c8068f1665783f0233f
F lib/type_info.h c5e26d4545acc1f15a95106b47f7d9e1a42ba2f9e3ddb0b8d653c4b9e2b38a1b
F lib/uds_connection.cpp a352c7da19ce1edf8ee57db3ab249af839fb6f7ccd0983146bc25c4087ae2f7e
F lib/uds_connection.h 4f35bc022706e0e03f68a5b5b727c709762af0ed9d674375f3f276e7d3cd5c59
F lib/utility.cpp 63e396efbf46336a08bbb56caf9c1a2642e396f29df22339df77b6c1616214ac
F lib/utility.h b4e321364dd5a98972e8100063cb7bbc83bf2cfbc09fa8f43b093d54dbfe69cf
F lib/vallist.cpp 9ea8d22a4e9c4326e5f5bd6e4dbbc9a5baa114cf4d197d46671fde3a3f945242
F lib/vallist.h cbbae0e30b0185301274d72cbf05d2c4f6ee1b06003c1978a651700cc45171c6
F lib/wnp_connection.cpp de966c60fd69b4d62c6e2cdf8e8741a40297d2d99207cfd2bed2f039b3a40cb2
F lib/wnp_connection.h bccc35d1af3f637f78f1dd400ef873017550ab3a896bedfd17a7614b4998fb24
F libmysqlclient.def 02e8547aed2a92862e8b2f498f9808ec59bc407603c0d547ffdeedd74a49a153
F mysql++.bkl a16f04171f08a925ad217fdc9a687cf63b9e43a725e66a064be2787aea67ac8f
F mysql++.ebuild 007ec3580f0562fb5db37f2ce011bf4cc797e9449e1e2b61ebd03afd57e57c51
F mysql++.spec.in ecc51cff6a7758f0c7186fef5be013873bea924507a81567f0195eb038523758
F osver 034cabb5f0517c3b0a3bedcf712289fd6b4b205ee9576940a1440dc85060c230 x
F pretty.pl 011358a7e49ceab10b1bcd5e8484edd2b28e3874723ffa95677b79f74ae7e010 l
F rebake.bat edb44b9acedd5fb9008b2f66a96f3e5dc525128384487a6ce52e9c5fbc19408f
F ssx/Doxyfile.in a066e3d1fecdc121d9e3754267cfc9de545f652c1d1a4fb8c7437baff1384c25
F ssx/genv2.cpp 64bfcd45ff394770da1e18d3163fc42427046286100ade51345bf1f8440fe271
F ssx/genv2.h 86b0944613f461c68b00703b1ee5cdbc99e773181f8ace99cc274cd1e08c76fa
F ssx/main.cpp db1743722b6f2868b00e95e0dce6a9f39f12aa9b11d28984e415d816ea853078

F ssx/parsev2.cpp 934b8385dd2dd27d9c2b7818f5f19667a0b7725e85d596d441cbba79a97e02ec
F ssx/parsev2.h de6fdfeecab8a96849ad351a32c5f83269bcfb99c88fb3e49cce129962856015
F test/array_index.cpp adbceb7e9e7e403a2a4484e81eefa5d13759e70987850c2e77ac10978256b46c

F test/cpool.cpp be6de03a0a847eea8f730ef35833447d278980c436c76bdf44f1aedcb20ed2d3
F test/datetime.cpp 9047e5ebbe9ace632bc89f529b26357a2fe7ac4d37bab5a60a6e6e241a60d57d
F test/insertpolicy.cpp 5a7114d4d9fe8c261dd3ba0aa919ae41cecbe3984a6609cc37b5611a794284ee
F test/inttypes.cpp c34b5e41c64b48283b0964c472e6c4ab1ecc1a328010e4cb406707a47f770ec6
F test/manip.cpp dceda6b2c16a4008cc5cd34503761b20268b023bc3d3e6626b62dd9538f31742
F test/null_comparison.cpp 75a312a0eccb4e6f31ebb0aa99a30590d6f97cad6df55bd462c09b3a93daec22
F test/null_uniqueness.cpp 2f559c7660e199105942c9e8e5078e9879ac5f6b12f8a58bc15a05a824b49d7c

F test/qssqls.cpp 5473f4fdba4870218fc36ac87d5bdb8e287fcd455260d2d297ebb43da1f2533c
F test/qstream.cpp 18be87d072ad4164261eb1c11039624a611cc057d9425b253afe7008832ad3dd
F test/query_copy.cpp d0d217a8e71dfb8c642678e53d3e069bd24072bdcbc0d4c18eebcbd4b3568816

F test/sqlstream.cpp 11254c5fdb9cfd0402d161770f428bca3f2cb17707d598f55bb39b8854695f8a
F test/ssqls2.cpp f302f79b2eff7e22088182d59f89e3508fbb5e663e670e24d21fe2d9910da0d9
F test/string.cpp ca2fea6f0d7cb9a394b28072764617ba1e50cb00de75ed9e78b2770a1cf1809b
F test/tcp.cpp aca2d45cd823a794cd56785d27ef1ef2e04cd4c5e7ca4a010b10ee08cb7f7042
F test/uds.cpp 31e025a2e6f475df255f3d8b6804b05bba25df96c691d5735208e283f099cb71
F test/wnp.cpp e78010d72bcffaf470d96d4dffb4889550f3c38fd0ab3d992b41e4297f224f92
P b916c0e1920aed0227f8a77be3a01f234004298da88f37750043b541169fab7c
R 4a85e5faa0490784eb6868cc86558c1b
T +sym-v3.1.0 *
U tangent
Z 474830967976254b8d8b5981d4b672e7

Changes to lib/transaction.h.

1
2
3
4
5
6
7
8
9
10

11
12

13





14
15
16
17
18
19




20
21
22
23
24
25
26
27
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
56
57
58
59

60
61
62
63

64
65
66
67
68
69
70
71
72



73
74
75
76
77





78
79


80
81
82
83

84
85
86
87

88


89

90
91
92
93
94
95
96
97
98
99
100
101
102



103
104
105

106
107
108
109
110


111
112


113




114
115
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


144
145
146
147

148


149


150
151
152
153
154




155
156
157
158





/// \file transaction.h
/// \brief Declares the Transaction class.
///
/// This object works with the Connection class to automate the use of
/// MySQL transactions.  It allows you to express these transactions
/// directly in C++ code instead of sending the raw SQL commands.

/***********************************************************************
 Copyright (c) 2006-2009 by Educational Technology Resources, Inc. and
 (c) 2008 by AboveNet, Inc.  Others may also hold copyrights on code

 in this file.  See the CREDITS.txt file in the top directory of the
 distribution for details.







 This file is part of MySQL++.

 MySQL++ is free software; you can redistribute it and/or modify it
 under the terms of the GNU Lesser General Public License as published
 by the Free Software Foundation; either version 2.1 of the License, or
 (at your option) any later version.





 MySQL++ is distributed in the hope that it will be useful, but WITHOUT
 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
 License for more details.

 You should have received a copy of the GNU Lesser General Public
 License along with MySQL++; if not, write to the Free Software
 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
 USA
***********************************************************************/





#if !defined(MYSQLPP_TRANSACTION_H)
#define MYSQLPP_TRANSACTION_H


#include "common.h"







namespace mysqlpp {


#if !defined(DOXYGEN_IGNORE)
// Make Doxygen ignore this
class MYSQLPP_EXPORT Connection;










#endif

/// \brief Helper object for creating exception-safe SQL transactions.

class MYSQLPP_EXPORT Transaction


{
public:
	/// \brief Transaction isolation levels defined in SQL
	///
	/// These values can be passed to one of the Transaction
	/// constructors to change the way the database engine protects
	/// transactions from other DB updates.  These values are in order
	/// of increasing isolation, but decreasing performance.
	enum IsolationLevel {
		read_uncommitted,	///< allow "dirty reads" from other transactions
		read_committed,		///< only read rows committed by other transactions
		repeatable_read,	///< other transactions do not affect repeated reads in this transaction
		serializable		///< this transaction prevents writes to any rows it accesses while it runs

	};

	/// \brief Isolation level scopes defined in SQL
	///

	/// These values are only used with one of the Transaction
	/// constructors, to select which transaction(s) our change to
	// the isolation scope will affect.
	enum IsolationScope {
		this_transaction,	///< change level for this transaction only
		session,			///< change level for all transactions in this session
		global				///< change level for all transactions on the DB server
	};




	/// \brief Simple constructor
	///
	/// \param conn The connection we use to manage the transaction set
	/// \param consistent Whether to use "consistent snapshots" during
	/// the transaction. See the documentation for "START TRANSACTION"





	/// in the MySQL manual for more on this.
	Transaction(Connection& conn, bool consistent = false);



	/// \brief Constructor allowing custom transaction isolation level
	/// and scope
	///

	/// \param conn The connection we use to manage the transaction set
	/// \param level Isolation level to use for this transaction
	/// \param scope Selects the scope of the isolation level change
	/// \param consistent Whether to use "consistent snapshots" during

	/// the transaction. See the documentation for "START TRANSACTION"


	/// in the MySQL manual for more on this.

	Transaction(Connection& conn, IsolationLevel level,
			IsolationScope scope = this_transaction,
			bool consistent = false);

	/// \brief Destructor
	///
	/// If the transaction has not been committed or rolled back by the
	/// time the destructor is called, it is rolled back.  This is the
	/// right thing because one way this can happen is if the object is
	/// being destroyed as the stack is unwound to handle an exception.
	/// In that instance, you certainly want to roll back the
	/// transaction.
	~Transaction();




	/// \brief Commits the transaction
	///

	/// This commits all updates to the database using the connection
	/// we were created with since this object was created.  This is a
	/// no-op if the table isn't stored using a transaction-aware
	/// storage engine.  See CREATE TABLE in the MySQL manual for
	/// details.


	void commit();



	/// \brief Rolls back the transaction




	///
	/// This abandons all SQL statements made on the connection since
	/// this object was created.  This only works on tables stored using
	/// a transaction-aware storage engine.  See CREATE TABLE in the

	/// MySQL manual for details.
	void rollback();


private:
	Connection& conn_;	///! Connection to send queries through
	bool finished_;		///! True when we commit or roll back xaction
};






/// \brief Compile-time substitute for Transaction, which purposely
/// does nothing.  Use it to instantiate templates that take Transaction
/// when you don't want transactions to be used.
///
/// This was created for use with InsertPolicy, used by
/// Query::insertfrom().  You might use it when your code already
/// wraps a given sequence of MySQL++ calls in a transaction and does
/// an insertfrom() as part of that.  MySQL doesn't support nested
/// transactions, so you need to suppress the one insertfrom() would
/// normally start.
class MYSQLPP_EXPORT NoTransaction
{
public:
	/// \brief Constructor
	NoTransaction(Connection&, bool = false)


	{






	}



	/// \brief Destructor
	~NoTransaction() { }


	/// \brief stub to replace Transaction::commit()


	void commit() { }



	/// \brief stub to replace Transaction::rollback()
	void rollback() { }
};





} // end namespace mysqlpp

#endif // !defined(MYSQLPP_TRANSACTION_H)






|
|
|
|
|
|

<
<
<
>
|
<
>

>
>
>
>
>
|

<
<
<
|
>
>
>
>
|
|
|
|
|
|
|
<
<
<
<

>
>
>
>
|
<

>
|
>
>
>
>
>
>

<
>
|
|
|
|
>
>
>
>
>
>
>
>
>
>
|

<

<
>
>
|
<
<
<
<
<
<
<
<
<
<
|
|
>
|
|
|
<
>
|
|
|
|
|
<
<
<

>
>
>
|
|
|
|
|
>
>
>
>
>
|
|
>
>

<
<
<
>
|
|
|
|
>
|
>
>
|
>
|
|
<

<
<
<
|
|
|
|
|
|
>
>
>

<
<
>
|
<
<
|
|
>
>
|
|
>
>
|
>
>
>
>
|
|
<
<
>
|
<
>

|
|
|
|
>
>
>
|
>
|
<
<
<
<
<
<
<
<
<
<
<
|
<
<
<
>
>
|
>
>
>
>
>
>
|
>
>
|
|
<

>
|
>
>
|
>
>

<
<
<

>
>
>
>
|

<
|
>
>
>
>
>
1
2
3
4
5
6
7



8
9

10
11
12
13
14
15
16
17
18



19
20
21
22
23
24
25
26
27
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
56
57
58
59
60
61
62
63

64

65
66
67










68
69
70
71
72
73

74
75
76
77
78
79



80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98



99
100
101
102
103
104
105
106
107
108
109
110
111

112



113
114
115
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
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
<?xml version="1.0" encoding='UTF-8'?>
<!DOCTYPE sect1 PUBLIC "-//OASIS//DTD DocBook V4.2//EN"
    "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">

<sect1 id="unicode" xreflabel="Using Unicode with MySQL++">
  <title>Using Unicode with MySQL++</title>




  <sect2 id="unicode-history">
    <title>A Short History of Unicode</title>

    <subtitle>...with a focus on relevance to MySQL++</subtitle>

    <para>In the old days, computer operating systems only dealt with
    8-bit character sets. That only allows for 256 possible characters,
    but the modern Western languages have more characters combined than
    that alone. Add in all the other languages of the world plus the
    various symbols people use in writing, and you have a real
    mess!</para>




    <para>Since no standards body held sway over things like
    international character encoding in the early days of computing,
    many different character sets were invented. These character sets
    weren&#x2019;t even standardized between operating systems, so heaven
    help you if you needed to move localized Greek text on a DOS box to
    a Russian Macintosh! The only way we got any international
    communication done at all was to build standards on top of the
    common 7-bit ASCII subset.  Either people used approximations like a
    plain &#x201C;c&#x201D; instead of the French &#x201C;&ccedil;&#x201D;,
    or they invented things like HTML entities
    (&#x201C;&amp;ccedil;&#x201D; in this case) to encode these additional
    characters using only 7-bit ASCII.</para>





    <para>Unicode solves this problem. It encodes every character used
    for writing in the world, using up to 4 bytes per character. The
    subset covering the most economically valuable cases takes two bytes
    per character, so most Unicode-aware programs deal in 2-byte
    characters, for efficiency.</para>


    <para>Unfortunately, Unicode was invented about two decades
    too late for Unix and C. Those decades of legacy created an
    immense inertia preventing a widespread move away from 8-bit
    characters. MySQL and C++ come out of these older traditions, and
    so they share the same practical limitations. MySQL++ currently
    doesn't have any code in it for Unicode conversions; it just
    passes data along unchanged from the underlying MySQL C API,
    so you still need to be aware of these underlying issues.</para>


    <para>During the development of the <ulink
    url="http://en.wikipedia.org/wiki/Plan_9_from_Bell_Labs">Plan
    9</ulink> operating system (a kind of successor to Unix) Ken
    Thompson <ulink
    url="http://www.cl.cam.ac.uk/~mgk25/ucs/utf-8-history.txt">invented</ulink>
    the <ulink url="http://en.wikipedia.org/wiki/UTF-8">UTF-8
    encoding</ulink>. UTF-8 is a superset of 7-bit ASCII and is
    compatible with C strings, since it doesn&#x2019;t use 0 bytes
    anywhere as multi-byte Unicode encodings do. As a result, many
    programs that deal in text will cope with UTF-8 data even though
    they have no explicit support for UTF-8. (Follow the last link above
    to see how the design of UTF-8 allows this.) Thus, when explicit
    support for Unicode was added in MySQL v4.1, they chose to make
    UTF-8 the native encoding, to preserve backward compatibility with
    programs that had no Unicode support.</para>
  </sect2>




  <sect2 id="unicode-unix">
    <title>Unicode on Unixy Systems</title>











    <para>Linux and Unix have system-wide UTF-8 support these days. If
    your operating system is of 2001 or newer vintage, it probably has
    such support.</para>

    <para>On such a system, the terminal I/O code understands UTF-8
    encoded data, so your program doesn&#x2019;t require any special code

    to correctly display a UTF-8 string. If you aren&#x2019;t sure
    whether your system supports UTF-8 natively, just run the
    <filename>simple1</filename> example: if the first item has two
    high-ASCII characters in place of the &#x201C;&uuml;&#x201D; in
    &#x201C;N&uuml;rnberger Brats&#x201D;, you know it&#x2019;s not
    handling UTF-8.</para>




    <para>If your Unix doesn&#x2019;t support UTF-8 natively, it likely
    doesn&#x2019;t support any form of Unicode at all, for the historical
    reasons I gave above. Therefore, you will have to convert the UTF-8
    data to the local 8-bit character set. The standard Unix function
    <function>iconv()</function> can help here. If your system
    doesn&#x2019;t have the <function>iconv()</function> facility, there
    is <ulink url="http://www.gnu.org/software/libiconv/">a free
    implementation</ulink> available from the GNU Project. Another
    library you might check out is IBM&#x2019;s <ulink
    url="http://icu.sourceforge.net/">ICU</ulink>. This is rather
    heavy-weight, so if you just need basic conversions,
    <function>iconv()</function> should suffice.</para>
  </sect2>


  <sect2 id="unicode-windows">
    <title>Unicode on Windows</title>




    <para>Each Windows API function that takes a string actually comes
    in two versions. One version supports only 1-byte &#x201C;ANSI&#x201D;
    characters (a superset of ASCII), so they end in 'A'. Windows also
    supports the 2-byte subset of Unicode called <ulink
    url="http://en.wikipedia.org/wiki/UCS-2">UCS-2</ulink>.  Some call
    these &#x201C;wide&#x201D; characters, so the other set of functions
    end in 'W'. The <function><ulink
    url="http://msdn.microsoft.com/library/en-us/winui/winui/windowsuserinterface/windowing/dialogboxes/dialogboxreference/dialogboxfunctions/messagebox.asp">MessageBox</ulink>()</function>
    API, for instance, is actually a macro, not a real function. If you
    define the <symbol>UNICODE</symbol> macro when building your
    program, the <function>MessageBox()</function> macro evaluates to
    <function>MessageBoxW()</function>; otherwise, to
    <function>MessageBoxA()</function>.</para>





    <para>Since MySQL uses the UTF-8 Unicode encoding and Windows uses
    UCS-2, you must convert data when passing text between MySQL++ and
    the Windows API. Since there&#x2019;s no point in trying for
    portability &mdash; no other OS I&#x2019;m aware of uses UCS-2
    &mdash; you might as well use platform-specific functions to do this
    translation. Since version 2.2.2, MySQL++ ships with two Visual C++
    specific examples showing how to do this in a GUI program.  (In
    earlier versions of MySQL++, we did Unicode conversion in the
    console mode programs, but this was unrealistic.)</para>



    <para>How you handle Unicode data depends on whether you&#x2019;re
    using the native Windows API, or the newer .NET API. First, the


    native case:</para>

    <programlisting>
// Convert a C string in UTF-8 format to UCS-2 format.
void ToUCS2(LPTSTR pcOut, int nOutLen, const char* kpcIn)
{
  MultiByteToWideChar(CP_UTF8, 0, kpcIn, -1, pcOut, nOutLen);
}

// Convert a UCS-2 string to C string in UTF-8 format.
void ToUTF8(char* pcOut, int nOutLen, LPCWSTR kpcIn)
{
  WideCharToMultiByte(CP_UTF8, 0, kpcIn, -1, pcOut, nOutLen, 0, 0);
}</programlisting>



    <para>These functions leave out some important error checking, so
    see <filename>examples/vstudio/mfc/mfc_dlg.cpp</filename> for the

    complete version.</para>

    <para>If you&#x2019;re building a .NET application (such as, perhaps,
    because you&#x2019;re using Windows Forms), it&#x2019;s better to use
    the .NET libraries for this:</para>

    <programlisting>
// Convert a C string in UTF-8 format to a .NET String in UCS-2 format.
String^ ToUCS2(const char* utf8)
{
  return gcnew String(utf8, 0, strlen(utf8), System::Text::Encoding::UTF8);
}















// Convert a .NET String in UCS-2 format to a C string in UTF-8 format.
System::Void ToUTF8(char* pcOut, int nOutLen, String^ sIn)
{
  array&lt;Byte&gt;^ bytes = System::Text::Encoding::UTF8->GetBytes(sIn);
  nOutLen = Math::Min(nOutLen - 1, bytes->Length);
  System::Runtime::InteropServices::Marshal::Copy(bytes, 0,
    IntPtr(pcOut), nOutLen);
  pcOut[nOutLen] = '\0';
}</programlisting>

    <para>Unlike the native API versions, these examples are complete,
    since the .NET platform handles a lot of things behind the scenes
    for us. We don&#x2019;t need any error-checking code for such simple
    routines.</para>


    <para>All of this assumes you&#x2019;re using Windows NT or one of
    its direct descendants: Windows 2000, Windows XP, Windows Vista, or
    any &#x201C;Server&#x201D; variant of Windows. Windows 95 and its
    descendants (98, ME, and CE) do not support UCS-2. They still have
    the 'W' APIs for compatibility, but they just smash the data down to
    8-bit and call the 'A' version for you.</para>
  </sect2>





  <sect2 id="unicode-refs">
    <title>For More Information</title>
      <para>The <ulink url="http://www.unicode.org/faq/">Unicode
      FAQs</ulink> page has copious information on this complex
      topic.</para>


      <para>When it comes to Unix and UTF-8 specific items, the <ulink
      url="http://www.cl.cam.ac.uk/~mgk25/unicode.html">UTF-8 and
      Unicode FAQ for Unix/Linux</ulink> is a quicker way to find basic
      information.</para>
    </sect2>
</sect1>

Changes to lib/type_info.cpp.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
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
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
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
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
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231





232
233
234
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
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
/***********************************************************************
 type_info.cpp - Implements the mysql_type_info class.

 Copyright (c) 1998 by Kevin Atkinson, (c) 1999-2001 by MySQL AB, and
 (c) 2004-2007 by Educational Technology Resources, Inc.  Others may
 also hold copyrights on code in this file.  See the CREDITS.txt file
 in the top directory of the distribution for details.

 This file is part of MySQL++.

 MySQL++ is free software; you can redistribute it and/or modify it
 under the terms of the GNU Lesser General Public License as published
 by the Free Software Foundation; either version 2.1 of the License, or
 (at your option) any later version.

 MySQL++ is distributed in the hope that it will be useful, but WITHOUT
 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
 License for more details.

 You should have received a copy of the GNU Lesser General Public
 License along with MySQL++; if not, write to the Free Software
 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
 USA
***********************************************************************/

#include "common.h"
#include "type_info.h"

#include "datetime.h"
#include "myset.h"
#include "sql_types.h"

#if defined(MYSQLPP_MYSQL_HEADERS_BURIED)
#	include <mysql/mysql.h>
#else
#	include <mysql.h>
#endif



#include <string>




using namespace std;

namespace mysqlpp {

// This table maps C++ type information to SQL type information.  As you
// can see, it's intimately tied in with MySQL's type constants, thus the
// name.  Unlike in earlier versions of MySQL++, this table is the only
// place with such a dependency.  Everything else abstracts MySQL's
// type system away by bouncing things through this table.
//
// The second half of the table parallels the first, to handle null-able
// versions of the types in the first half.  This is required because
// SQL's 'null' concept does not map neatly into the C++ type system, so
// null-able versions of these types have to have a different C++ type,
// implemented using the Null template.  See null.h for further details.
//
// Types with tf_default set are added to a lookup map in the
// mysql_type_info_lookup class in order to provide reverse lookup
// of C++ types to SQL types.  If you take the subset of all items
// marked as default, the typeid() of each item must be unique.
const mysql_type_info::sql_type_info mysql_type_info::types[] = {
	sql_type_info("DECIMAL NOT NULL", typeid(sql_decimal),
#if MYSQL_VERSION_ID >= 50001
			MYSQL_TYPE_NEWDECIMAL
#else
			MYSQL_TYPE_DECIMAL
#endif
			),
	sql_type_info("TINYINT NOT NULL", typeid(sql_tinyint),
			MYSQL_TYPE_TINY, mysql_ti_sql_type_info::tf_default),
	sql_type_info("TINYINT UNSIGNED NOT NULL", typeid(sql_tinyint_unsigned),
			MYSQL_TYPE_TINY, mysql_ti_sql_type_info::tf_default |
			mysql_ti_sql_type_info::tf_unsigned),
	sql_type_info("SMALLINT NOT NULL", typeid(sql_smallint),
			MYSQL_TYPE_SHORT, mysql_ti_sql_type_info::tf_default),
	sql_type_info("SMALLINT UNSIGNED NOT NULL", typeid(sql_smallint_unsigned),
			MYSQL_TYPE_SHORT, mysql_ti_sql_type_info::tf_default |
			mysql_ti_sql_type_info::tf_unsigned),
	sql_type_info("INT NOT NULL", typeid(sql_int),
			MYSQL_TYPE_LONG, mysql_ti_sql_type_info::tf_default),
	sql_type_info("INT UNSIGNED NOT NULL", typeid(sql_int_unsigned),
			MYSQL_TYPE_LONG, mysql_ti_sql_type_info::tf_default |
			mysql_ti_sql_type_info::tf_unsigned),
	sql_type_info("FLOAT NOT NULL", typeid(sql_float),
			MYSQL_TYPE_FLOAT, mysql_ti_sql_type_info::tf_default),
	sql_type_info("FLOAT UNSIGNED NOT NULL", typeid(sql_float),
			MYSQL_TYPE_FLOAT, mysql_ti_sql_type_info::tf_default |
			mysql_ti_sql_type_info::tf_unsigned),
	sql_type_info("DOUBLE NOT NULL", typeid(sql_double),
			MYSQL_TYPE_DOUBLE, mysql_ti_sql_type_info::tf_default),
	sql_type_info("DOUBLE UNSIGNED NOT NULL", typeid(sql_double),
			MYSQL_TYPE_DOUBLE, mysql_ti_sql_type_info::tf_default |
			mysql_ti_sql_type_info::tf_unsigned),
	sql_type_info("NULL NOT NULL", typeid(void),
			MYSQL_TYPE_NULL, mysql_ti_sql_type_info::tf_default),
	sql_type_info("TIMESTAMP NOT NULL", typeid(sql_timestamp),
			MYSQL_TYPE_TIMESTAMP),
	sql_type_info("BIGINT NOT NULL", typeid(sql_bigint),
			MYSQL_TYPE_LONGLONG, mysql_ti_sql_type_info::tf_default),
	sql_type_info("BIGINT UNSIGNED NOT NULL", typeid(sql_bigint_unsigned),
			MYSQL_TYPE_LONGLONG, mysql_ti_sql_type_info::tf_default |
			mysql_ti_sql_type_info::tf_unsigned),
	sql_type_info("MEDIUMINT NOT NULL", typeid(sql_mediumint),
			MYSQL_TYPE_INT24, mysql_ti_sql_type_info::tf_unsigned),
	sql_type_info("MEDIUMINT UNSIGNED NOT NULL", typeid(sql_mediumint_unsigned),
			MYSQL_TYPE_INT24, mysql_ti_sql_type_info::tf_unsigned),
	sql_type_info("DATE NOT NULL", typeid(sql_date),
			MYSQL_TYPE_DATE, mysql_ti_sql_type_info::tf_default),
	sql_type_info("TIME NOT NULL", typeid(sql_time),
			MYSQL_TYPE_TIME, mysql_ti_sql_type_info::tf_default),
	sql_type_info("DATETIME NOT NULL", typeid(sql_datetime),
			MYSQL_TYPE_DATETIME, mysql_ti_sql_type_info::tf_default),
	sql_type_info("ENUM NOT NULL", typeid(sql_enum),
			MYSQL_TYPE_ENUM, mysql_ti_sql_type_info::tf_default),
	sql_type_info("SET NOT NULL", typeid(sql_set),
			MYSQL_TYPE_SET, mysql_ti_sql_type_info::tf_default),
	sql_type_info("TINYBLOB NOT NULL", typeid(sql_tinyblob),
			MYSQL_TYPE_TINY_BLOB),
	sql_type_info("MEDIUMBLOB NOT NULL", typeid(sql_mediumblob),
			MYSQL_TYPE_MEDIUM_BLOB),
	sql_type_info("LONGBLOB NOT NULL", typeid(sql_longblob),
			MYSQL_TYPE_LONG_BLOB),
	sql_type_info("BLOB NOT NULL", typeid(sql_blob),
			MYSQL_TYPE_BLOB, mysql_ti_sql_type_info::tf_default),
	sql_type_info("VARCHAR NOT NULL", typeid(sql_varchar),
			MYSQL_TYPE_VAR_STRING, mysql_ti_sql_type_info::tf_default),
	sql_type_info("CHAR NOT NULL", typeid(sql_char),
			MYSQL_TYPE_STRING),

	sql_type_info("DECIMAL NULL", typeid(Null<sql_decimal>),
#if MYSQL_VERSION_ID >= 50001
			MYSQL_TYPE_NEWDECIMAL
#else
			MYSQL_TYPE_DECIMAL
#endif
			, mysql_ti_sql_type_info::tf_null),
	sql_type_info("TINYINT NULL", typeid(Null<sql_tinyint>),
			MYSQL_TYPE_TINY, mysql_ti_sql_type_info::tf_default |
			mysql_ti_sql_type_info::tf_null),
	sql_type_info("TINYINT UNSIGNED NULL", typeid(Null<sql_tinyint_unsigned>),
			MYSQL_TYPE_TINY, mysql_ti_sql_type_info::tf_default |









			mysql_ti_sql_type_info::tf_null |
			mysql_ti_sql_type_info::tf_unsigned),
	sql_type_info("SMALLINT NULL", typeid(Null<sql_smallint>),
			MYSQL_TYPE_SHORT, mysql_ti_sql_type_info::tf_default |
			mysql_ti_sql_type_info::tf_null),
	sql_type_info("SMALLINT UNSIGNED NULL", typeid(Null<sql_smallint_unsigned>),
			MYSQL_TYPE_SHORT, mysql_ti_sql_type_info::tf_default |
			mysql_ti_sql_type_info::tf_null |
			mysql_ti_sql_type_info::tf_unsigned),
	sql_type_info("INT NULL", typeid(Null<sql_int>),
			MYSQL_TYPE_LONG, mysql_ti_sql_type_info::tf_default |
			mysql_ti_sql_type_info::tf_null),
	sql_type_info("INT UNSIGNED NULL", typeid(Null<sql_int_unsigned>),
			MYSQL_TYPE_LONG, mysql_ti_sql_type_info::tf_default |
			mysql_ti_sql_type_info::tf_null |
			mysql_ti_sql_type_info::tf_unsigned),
	sql_type_info("FLOAT NULL", typeid(Null<sql_float>),
			MYSQL_TYPE_FLOAT, mysql_ti_sql_type_info::tf_default |
			mysql_ti_sql_type_info::tf_null),
	sql_type_info("FLOAT UNSIGNED NULL", typeid(Null<sql_float>),
			MYSQL_TYPE_FLOAT, mysql_ti_sql_type_info::tf_default |
			mysql_ti_sql_type_info::tf_null |
			mysql_ti_sql_type_info::tf_unsigned),
	sql_type_info("DOUBLE NULL", typeid(Null<sql_double>),
			MYSQL_TYPE_DOUBLE, mysql_ti_sql_type_info::tf_default |
			mysql_ti_sql_type_info::tf_null),
	sql_type_info("DOUBLE UNSIGNED NULL", typeid(Null<sql_double>),
			MYSQL_TYPE_DOUBLE, mysql_ti_sql_type_info::tf_default |
			mysql_ti_sql_type_info::tf_null |
			mysql_ti_sql_type_info::tf_unsigned),
	sql_type_info("NULL NULL", typeid(Null<void>),
			MYSQL_TYPE_NULL, mysql_ti_sql_type_info::tf_null),
	sql_type_info("TIMESTAMP NULL", typeid(Null<sql_timestamp>),
			MYSQL_TYPE_TIMESTAMP),
	sql_type_info("BIGINT NULL", typeid(Null<sql_bigint>),
			MYSQL_TYPE_LONGLONG, mysql_ti_sql_type_info::tf_default |
			mysql_ti_sql_type_info::tf_null),
	sql_type_info("BIGINT UNSIGNED NULL", typeid(Null<sql_bigint_unsigned>),
			MYSQL_TYPE_LONGLONG, mysql_ti_sql_type_info::tf_default |
			mysql_ti_sql_type_info::tf_null |
			mysql_ti_sql_type_info::tf_unsigned),
	sql_type_info("MEDIUMINT NULL", typeid(Null<sql_mediumint>),
			MYSQL_TYPE_INT24, mysql_ti_sql_type_info::tf_null),
	sql_type_info("MEDIUMINT UNSIGNED NULL", typeid(Null<sql_mediumint_unsigned>), 
			MYSQL_TYPE_INT24, mysql_ti_sql_type_info::tf_null |
			mysql_ti_sql_type_info::tf_unsigned),
	sql_type_info("DATE NULL", typeid(Null<sql_date>),
			MYSQL_TYPE_DATE, mysql_ti_sql_type_info::tf_default |
			mysql_ti_sql_type_info::tf_null),
	sql_type_info("TIME NULL", typeid(Null<sql_time>),
			MYSQL_TYPE_TIME, mysql_ti_sql_type_info::tf_default |
			mysql_ti_sql_type_info::tf_null),
	sql_type_info("DATETIME NULL", typeid(Null<sql_datetime>),
			MYSQL_TYPE_DATETIME, mysql_ti_sql_type_info::tf_default |
			mysql_ti_sql_type_info::tf_null),
	sql_type_info("ENUM NULL", typeid(Null<sql_enum>),
			MYSQL_TYPE_ENUM, mysql_ti_sql_type_info::tf_default |
			mysql_ti_sql_type_info::tf_null),
	sql_type_info("SET NULL", typeid(Null<sql_set>),
			MYSQL_TYPE_SET, mysql_ti_sql_type_info::tf_default |
			mysql_ti_sql_type_info::tf_null),
	sql_type_info("TINYBLOB NULL", typeid(Null<sql_tinyblob>),
			MYSQL_TYPE_TINY_BLOB, mysql_ti_sql_type_info::tf_null),
	sql_type_info("MEDIUMBLOB NULL", typeid(Null<sql_mediumblob>),
			MYSQL_TYPE_MEDIUM_BLOB, mysql_ti_sql_type_info::tf_null),
	sql_type_info("LONGBLOB NULL", typeid(Null<sql_longblob>),
			MYSQL_TYPE_LONG_BLOB, mysql_ti_sql_type_info::tf_null),
	sql_type_info("BLOB NULL", typeid(Null<sql_blob>),
			MYSQL_TYPE_BLOB, mysql_ti_sql_type_info::tf_default |
			mysql_ti_sql_type_info::tf_null),
	sql_type_info("VARCHAR NULL", typeid(Null<sql_varchar>),
			MYSQL_TYPE_VAR_STRING, mysql_ti_sql_type_info::tf_default |
			mysql_ti_sql_type_info::tf_null),
	sql_type_info("CHAR NULL", typeid(Null<sql_char>),
			MYSQL_TYPE_STRING, mysql_ti_sql_type_info::tf_null)
};

const int mysql_type_info::num_types =
		sizeof(mysql_type_info::types) / sizeof(mysql_type_info::types[0]);

const mysql_type_info::sql_type_info_lookup
		mysql_type_info::lookups(mysql_type_info::types,
		mysql_type_info::num_types);

#if !defined(DOXYGEN_IGNORE)
// Doxygen will not generate documentation for this section.

mysql_ti_sql_type_info_lookup::mysql_ti_sql_type_info_lookup(
		const sql_type_info types[], const int size)





{
	for (int i = 0; i < size; ++i) {
		if (types[i].is_default()) {
			map_[types[i].c_type_] = i;
		}
	}
}

#endif // !defined(DOXYGEN_IGNORE)

unsigned char mysql_type_info::type(enum_field_types t,
		bool _unsigned, bool _null)
{
	for (unsigned char i = 0; i < num_types; ++i) {
		if ((types[i].base_type_ == t) &&
				(!_unsigned || types[i].is_unsigned()) &&
				(!_null || types[i].is_null())) {
			return i;
		}
	}


	return type(MYSQL_TYPE_STRING, false, _null);	// punt!
}


bool mysql_type_info::quote_q() const
{
	const type_info& ti = base_type().c_type();
	return ti == typeid(string) ||
			ti == typeid(sql_date) ||
			ti == typeid(sql_time) ||
			ti == typeid(sql_datetime) ||
			ti == typeid(sql_blob) ||
			ti == typeid(sql_tinyblob) ||
			ti == typeid(sql_mediumblob) ||
			ti == typeid(sql_longblob) ||
			ti == typeid(sql_char) ||
			ti == typeid(sql_set);
}

bool mysql_type_info::escape_q() const
{
	const type_info& ti = base_type().c_type();
	return ti == typeid(string) ||
			ti == typeid(sql_enum) ||
			ti == typeid(sql_blob) ||
			ti == typeid(sql_tinyblob) ||
			ti == typeid(sql_mediumblob) ||
			ti == typeid(sql_longblob) ||
			ti == typeid(sql_char) ||
			ti == typeid(sql_varchar);
}

} // end namespace mysqlpp

<
<
|
<
<
<
<
|
<
|
<
<
<
<

<
<
<
|
|
<
<
<
<
<

<
<
|
<
<
<
|
|
<
<
<
<

>
>
|

>
>
>
|

<

<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
|
|
<
<
<
<
|
|
|
|
|
|
|
|
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
|
|
|
|
|
|
|
|
|
|
|
|
<
<
<
<
<
<
<
<
<
<
<

<
<
<
<
<
<
<
<
<
<
<
<
>
>
>
>
>
>
>
>
>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<

<
<
|
<
<
<
|
<
<
|
<
<
>
>
>
>
>
|
<
<
<
|
<
<
|
<
|
<
<
<
<
<
<
<
<
|
<
|
>
|
<
|
>
|
|
|
|
|
|
|
|
|
|
<
<
<
<
|
<
<
<
<
<
<
<
<
<
<
<
<
|
<
|


1




2

3




4



5
6





7


8



9
10




11
12
13
14
15
16
17
18
19
20

21




















22
23




24
25
26
27
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
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75














76
77
78
79
80
81
82
83
84
85
86
87
88
89



























90


91



92


93


94
95
96
97
98
99



100


101

102








103

104
105
106

107
108
109
110
111
112
113
114
115
116
117
118




119












120

121


<?xml version="1.0" encoding="UTF-8"?>




<!DOCTYPE sect1 PUBLIC "-//OASIS//DTD DocBook V4.2//EN"

    "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">








<sect1 id="intro">
  <title>Introduction</title>








  <para>MySQL++ is a powerful C++ wrapper for MySQL&#x2019;s C API.  Its



  purpose is to make working with queries as easy as working with STL
  containers.</para>





  <para>The latest version of MySQL++ can be found at <ulink
  url="http://tangentsoft.net/mysql++/">the official web
  site</ulink>.</para>

  <para>Support for MySQL++ can be had on <ulink
  url="http://lists.mysql.com/plusplus">the mailing list</ulink>. That
  page hosts the mailing list archives, and tells you how you can
  subscribe.</para>























  <sect2 id="history">
    <title>A Brief History of MySQL++</title>





    <para>MySQL++ was created in 1998 by Kevin Atkinson. It started
    out MySQL-specific, but there were early efforts to try and
    make it database-independent, and call it SQL++. This is where
    the old library name &#x201C;sqlplus&#x201D; came from. This
    is also why the old versions prefixed some class names with
    &#x201C;Mysql&#x201D; but not others: the others were supposed to
    be the database-independent parts. All of Kevin&#x2019;s releases
    had pre-1.0 version numbers.</para>



























    <para>Then in 1999, <ulink url="http://www.mysql.com/">MySQL
    AB</ulink> took over development of the library. In the beginning,
    <ulink url="http://en.wikipedia.org/wiki/Monty_Widenius">Monty
    Widenius</ulink> himself did some of the work, but later gave it
    over to another MySQL employee, Sinisa Milivojevic. MySQL released
    versions 1.0 and 1.1, and then Kevin gave over maintenance to
    Sinisa officially with 1.2, and ceased to have any involvement
    with the library&#x2019;s maintenance. Sinisa went on to maintain
    the library through 1.7.9, released in mid-2001. It seems to be
    during this time that the dream of multiple-database compatibility
    died, for obvious reasons.</para>
























    <para>With version 1.7.9, MySQL++ went into a period of
    stasis, lasting over three years. (Perhaps it was the
    ennui and retrenchment following the collapse of <ulink
    url="http://en.wikipedia.org/wiki/Dot-com_bubble">the
    bubble</ulink> that caused them to lose interest.) During this
    time, Sinisa ran the MySQL++ mailing list and supported its users,
    but made no new releases. Contributed patches were either ignored
    or put up on the MySQL++ web site for users to try, without any
    official blessing.</para>

    <para>The biggest barrier to using MySQL++ during this period
    is that the popular C++ compilers of 2001 weren&#x2019;t all
    that compatible with the C++ Standard. As a result, MySQL++
    used many nonstandard constructs, to allow for compatibility
    with older compilers. Each new compiler released in the
    following years increased compliance, either warning
    about or rejecting code using pre-Standard constructs.
    In particular, <ulink url="http://gcc.gnu.org/">GCC</ulink>
    was emerging from the mess following the <ulink
    url="http://en.wikipedia.org/wiki/GNU_Compiler_Collection#EGCS">EGCS
    fork</ulink> during this time. The fork was healed officially
    in 1999, but there&#x2019;s always a delay of a few years between
    the release of a new GCC and widespread adoption. The post-EGCS
    versions of GCC were only beginning to become popular by 2001,
    when development on MySQL++ halted. As a result, it became
    increasingly difficult to get MySQL++ to build cleanly as newer
    compilers came out. Since MySQL++ uses templates heavily, this
    affected end user programs as well: MySQL++ code got included
    directly in your program, so any warnings or errors it caused
    became your program&#x2019;s problem.</para>















    <para>As a result, most of the patches contributed to the MySQL++
    project during this period were to fix up standards compliance
    issues. Because no one was bothering to officially test and bless
    these patches, you ended up with the worst aspects of a <ulink
    url="http://en.wikipedia.org/wiki/The_Cathedral_and_the_Bazaar">bazaar</ulink>
    development model: complete freedom of development, but no guiding
    hand to select from the good stuff and reject the rest. Many of the
    patches were mutually incompatible. Some would build upon other
    patches, so you had to apply them in the proper sequence. Others
    did useful things, but didn&#x2019;t give a fully functional copy of
    MySQL++. Figuring out which patch(es) to use was an increasingly
    frustrating exercise as the years wore on, and newer GCCs became
    popular.</para>






























    <para>In early August of 2004, Warren Young got fed up with this



    situation and took over. He released 1.7.10 later that month,


    which did little more than make the code build with GCC 3.3 without


    warnings. Since then, with a little help from his friends on the
    Net, MySQL++ has lost a lot of bugs, gained a lot of features,
    gained a few more bugs, lost them again... MySQL++ is alive and
    healthy now.</para>
  </sect2>







  <sect2 id="asking-questions">

    <title>If You Have Questions...</title>










    <para>If you want to email someone to ask questions about
    this library, we greatly prefer that you send mail to the
    <ulink url="http://lists.mysql.com/plusplus">MySQL++ mailing

    list</ulink>. The mailing list is archived, so if you have
    questions, do a search to see if the question has been asked
    before.</para>

    <para>You may find people&#x2019;s individual email addresses in various
    files within the MySQL++ distribution. Please do not send mail
    to them unless you are sending something that is inherently
    personal. Not all of the principal developers of MySQL++ are still
    active in its development; those who have dropped out have no wish
    to be bugged about MySQL++. Those of us still active in MySQL++
    development monitor the mailing list, so you aren&#x2019;t getting any
    extra &#x201C;coverage&#x201D; by sending messages to additional




    email addresses.</para>












  </sect2>

</sect1>

Changes to lib/type_info.h.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
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
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
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
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
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223




224
225

226
227
228
229

230
231
232

233
234
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
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
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
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358

/// \file type_info.h
/// \brief Declares classes that provide an interface between the SQL
/// and C++ type systems.
///
/// These classes are mostly used internal to the library.

/***********************************************************************
 Copyright (c) 1998 by Kevin Atkinson, (c) 1999-2001 by MySQL AB, and
 (c) 2004-2008 by Educational Technology Resources, Inc.  Others may
 also hold copyrights on code in this file.  See the CREDITS.txt file
 in the top directory of the distribution for details.

 This file is part of MySQL++.

 MySQL++ is free software; you can redistribute it and/or modify it
 under the terms of the GNU Lesser General Public License as published
 by the Free Software Foundation; either version 2.1 of the License, or
 (at your option) any later version.

 MySQL++ is distributed in the hope that it will be useful, but WITHOUT
 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
 License for more details.

 You should have received a copy of the GNU Lesser General Public
 License along with MySQL++; if not, write to the Free Software
 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
 USA
***********************************************************************/

#if !defined(MYSQLPP_TYPE_INFO_H)
#define MYSQLPP_TYPE_INFO_H

#include "common.h"

#include "exceptions.h"

#include <map>
#include <sstream>
#include <typeinfo>

namespace mysqlpp {

#if !defined(DOXYGEN_IGNORE)
// Doxygen will not generate documentation for this section.

class MYSQLPP_EXPORT mysql_type_info;
class MYSQLPP_EXPORT mysql_ti_sql_type_info_lookup;

class MYSQLPP_EXPORT mysql_ti_sql_type_info
{
private:
	// For use with flags_ bitset
	enum {
		tf_default = 1,
		tf_null = 2,
		tf_unsigned = 4
	};

	friend class mysql_type_info;
	friend class mysql_ti_sql_type_info_lookup;

	mysql_ti_sql_type_info& operator=(
			const mysql_ti_sql_type_info& b);
	
	// Not initting _base_type and _default because only mysql_type_info
	// can create them.  There *must* be only one copy of each.
	mysql_ti_sql_type_info() :
	sql_name_(0),
	c_type_(0),
	base_type_(
#if MYSQL_VERSION_ID > 40000
		MYSQL_TYPE_NULL
#else
		FIELD_TYPE_NULL
#endif
	),
	flags_(0)
	{
	}
	
	mysql_ti_sql_type_info(const char* s,
			const std::type_info& t, const enum_field_types bt,
			const unsigned int flags = 0) :
	sql_name_(s),
	c_type_(&t),
	base_type_(bt),
	flags_(flags)
	{
	}

	bool is_default() const { return flags_ & tf_default; }
	bool is_null() const { return flags_ & tf_null; }
	bool is_unsigned() const { return flags_ & tf_unsigned; }

	const char* sql_name_;
	const std::type_info* c_type_;
	const enum_field_types base_type_;
	const unsigned int flags_;
};


struct type_info_cmp
{
	bool operator() (const std::type_info* lhs,
			const std::type_info* rhs) const
	{
		return lhs->before(*rhs) != 0;
	}
};

class MYSQLPP_EXPORT mysql_ti_sql_type_info_lookup
{
private:
	friend class mysql_type_info;

	typedef mysql_ti_sql_type_info sql_type_info;
	typedef std::map<const std::type_info*, unsigned char, type_info_cmp>
			map_type;

	mysql_ti_sql_type_info_lookup(const sql_type_info types[],
			const int size);

	const unsigned char& operator [](
			const std::type_info& ti) const
	{
		map_type::const_iterator it = map_.find(&ti);
		if (it != map_.end()) {
			return it->second;
		}
		else {
			std::ostringstream outs;
			outs << "Failed to find MySQL C API type ID for " << ti.name();
			throw TypeLookupFailed(outs.str());
		}
	}


	map_type map_;
};


#endif // !defined(DOXYGEN_IGNORE)


/// \brief SQL field type information
///

/// \internal Used within MySQL++ for mapping SQL types to C++ types
/// and vice versa.
class MYSQLPP_EXPORT mysql_type_info
{

public:
	/// \brief Default constructor
	///

	/// This only exists because FieldTypes keeps a vector of these
	/// objects.  You are expected to copy real values into it before
	/// using it via the copy ctor or one of the assignment operators.
	/// If you don't, we have arranged a pretty spectacular crash for
	/// your program.  So there.
	mysql_type_info() :
	num_(static_cast<unsigned char>(-1))
	{
	}




	/// \brief Create object from MySQL C API type info
	///
	/// \param t the underlying C API type ID for this type
	/// \param _unsigned if true, this is the unsigned version of the type
	/// \param _null if true, this type can hold a SQL null
	mysql_type_info(enum_field_types t, bool _unsigned = false,
			bool _null = false) :
	num_(type(t, _unsigned, _null))
	{
	}



	/// \brief Create object as a copy of another
	mysql_type_info(const mysql_type_info& t) :
	num_(t.num_)
	{
	}









	/// \brief Create object from a C++ type_info object
	///
	/// This tries to map a C++ type to the closest MySQL data type.
	/// It is necessarily somewhat approximate.

	mysql_type_info(const std::type_info& t) :
	num_(lookups[t])
	{
	}

	/// \brief Assign another mysql_type_info object to this object
	mysql_type_info& operator =(const mysql_type_info& t)
	{
		num_ = t.num_;
		return *this;
	}

	/// \brief Assign a C++ type_info object to this object
	///
	/// This tries to map a C++ type to the closest MySQL data type.
	/// It is necessarily somewhat approximate.
	mysql_type_info& operator =(const std::type_info& t)
	{
		num_ = lookups[t];
		return *this;
	}

	/// \brief Returns an implementation-defined name of the C++ type.
	///
	/// Returns the name that would be returned by typeid().name() for
	/// the C++ type associated with the SQL type.
	const char* name() const { return deref().c_type_->name(); }

	/// \brief Returns the name of the SQL type.
	///
	/// Returns the SQL name for the type.
	const char* sql_name() const { return deref().sql_name_; }

	/// \brief Returns the type_info for the C++ type associated with
	/// the SQL type.
	///
	/// Returns the C++ type_info record corresponding to the SQL type.
	const std::type_info& c_type() const { return *deref().c_type_; }

	/// \brief Returns the type_info for the C++ type inside of the




	/// mysqlpp::Null type.
	///

	/// Returns the type_info for the C++ type inside the mysqlpp::Null
	/// type.  If the type is not Null then this is the same as c_type().
	const mysql_type_info base_type() const
	{

		return mysql_type_info(deref().base_type_);
	}


	/// \brief Returns the ID of the SQL type.
	///
	/// Returns the ID number MySQL uses for this type.  Note: Do not
	/// depend on the value of this ID as it may change between MySQL
	/// versions.
	int id() const
	{
		return num_;
	}
	
	/// \brief Returns true if the SQL type is of a type that needs to
	/// be quoted.
	///
	/// \return true if the type needs to be quoted for syntactically
	/// correct SQL.
	bool quote_q() const;

	/// \brief Returns true if the SQL type is of a type that needs to
	/// be escaped.
	///
	/// \return true if the type needs to be escaped for syntactically
	/// correct SQL.
	bool escape_q() const;

	/// \brief Provides a way to compare two types for sorting.
	///
	/// Returns true if the SQL ID of this type is lower than that of
	/// another.  Used by mysqlpp::type_info_cmp when comparing types.
	bool before(mysql_type_info& b)
	{
		return num_ < b.num_;
	}

	/// \brief The internal constant we use for our string type.
	///
	/// We expose this because other parts of MySQL++ need to know
	/// what the string constant is at the moment.
	static const enum_field_types string_type =
#if MYSQL_VERSION_ID > 40000

		MYSQL_TYPE_STRING;
#else
		FIELD_TYPE_STRING;
#endif

private:
	typedef mysql_ti_sql_type_info sql_type_info;
	typedef mysql_ti_sql_type_info_lookup sql_type_info_lookup;

	static const sql_type_info types[];
	static const int num_types;

	static const sql_type_info_lookup lookups;

	/// \brief Return an index into mysql_type_info::types array given
	/// MySQL type information.
	///
	/// This function is used in mapping from MySQL type information
	/// (a type enum, and flags indicating whether it is unsigned and
	/// whether it can be 'null') to the closest C++ types available
	/// within MySQL++.  Notice that nulls have to be handled specially:
	/// the SQL null concept doesn't map directly onto the C++ type
	/// system.  See null.h for details.
	///
	/// \param t Underlying C API type constant
	/// \param _unsigned if true, indicates the unsigned variant of a
	/// MySQL type
	/// \param _null if true, indicates the variant of the MySQL type
	/// that can also hold an SQL 'null' instead of regular data.
	///
	/// While MySQL++ is tied to MySQL, \c t is just an abstraction
	/// of enum_field_types from mysql_com.h.
	static unsigned char type(enum_field_types t,
			bool _unsigned, bool _null = false);

	const sql_type_info& deref() const
	{
		return types[num_];
	}

	unsigned char num_;
};


/// \brief Returns true if two mysql_type_info objects are equal.
inline bool operator ==(const mysql_type_info& a, const mysql_type_info& b)
{

	return a.id() == b.id();
}

/// \brief Returns true if two mysql_type_info objects are not equal.
inline bool operator !=(const mysql_type_info& a, const mysql_type_info& b)
{
	return a.id() != b.id();
}

/// \brief Returns true if a given mysql_type_info object is equal
/// to a given C++ type_info object.
inline bool operator ==(const std::type_info& a, const mysql_type_info& b)
{
	return a == b.c_type();
}

/// \brief Returns true if a given mysql_type_info object is not equal
/// to a given C++ type_info object.
inline bool operator !=(const std::type_info& a, const mysql_type_info& b)
{
	return a != b.c_type();
}

/// \brief Returns true if a given mysql_type_info object is equal
/// to a given C++ type_info object.
inline bool operator ==(const mysql_type_info& a, const std::type_info& b)
{
	return a.c_type() == b;
}

/// \brief Returns true if a given mysql_type_info object is not equal
/// to a given C++ type_info object.
inline bool operator !=(const mysql_type_info& a, const std::type_info& b)
{
	return a.c_type() != b;
}

}								// end namespace mysqlpp

#endif // !defined(MYSQLPP_TYPE_INFO_H)


<
<
<
<
<
|
<
<
<
<
<
|
<
|
<
<
<
<
|
<
<
<
<
|
<
<
<
<
<

<
<
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
|
<
|
>
|
<
|
>
|
|
|
|
<
>
|
|
|
<
>
|
|
<
>
|
<
<
<
<
|
<
<
<
>
>
>
|
|
|
|
|
|
|
|
|
<
<
|
>
>
|
|
|
<
<
|
>
>
>
>
>
>
>
>
|
<
<
<
>
|
<
<
<
|
<
<
<
|
<
<
|
<
<
<
<
<
<
<
<
<
|
<
<
<
<
<
|
<
<
<
<
|
<
<
<
<
<
|
<
>
>
>
>
|
<
>
|
|
|
<
>
|
<
|
>
|
<
<
<
<
<
<
<
<
|
<
<
<
<
<
<
|
<
<
<
<
<
<
|
<
<
<
<
<
<
<
<
|
<
<
<
|
<
|
>
|
|
|
<
|
<
<
<
|
<
<
|
<
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
|
<
<
|
<
<
<
<
|
<
<
>
|
|
|
<
>
|
<
|
<
<
<
<
<
|
<
<
<
<
<
<
|
<
<
<
<
<
<
|
<
<
<
<
<
<
|
<
<
<
<
<
<
|
<
|
<
|
>





1





2

3




4




5





6


7





































































































8

9
10
11

12
13
14
15
16
17

18
19
20
21

22
23
24

25
26




27



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



56
57



58



59


60









61





62




63





64

65
66
67
68
69

70
71
72
73

74
75

76
77
78








79






80






81








82



83

84
85
86
87
88

89



90


91

92

















93


94




95


96
97
98
99

100
101

102





103






104






105






106






107

108

109
110





dnl ### begin block 00_header[./mysql++.bkl] ###





dnl

dnl This macro was generated by




dnl Bakefile 0.2.5 (http://www.bakefile.org)




dnl Do not modify, all changes will be overwritten!








BAKEFILE_AUTOCONF_INC_M4_VERSION="0.2.5"







































































































dnl ### begin block 20_COND_BUILD_debug[./mysql++.bkl] ###
    COND_BUILD_debug="#"
    if test "x$BUILD" = "xdebug" ; then

        COND_BUILD_debug=""
    fi
    AC_SUBST(COND_BUILD_debug)
dnl ### begin block 20_COND_BUILD_release[./mysql++.bkl] ###
    COND_BUILD_release="#"
    if test "x$BUILD" = "xrelease" ; then

        COND_BUILD_release=""
    fi
    AC_SUBST(COND_BUILD_release)
dnl ### begin block 20_COND_DEPS_TRACKING_0[./mysql++.bkl] ###

    COND_DEPS_TRACKING_0="#"
    if test "x$DEPS_TRACKING" = "x0" ; then
        COND_DEPS_TRACKING_0=""

    fi
    AC_SUBST(COND_DEPS_TRACKING_0)




dnl ### begin block 20_COND_DEPS_TRACKING_1[./mysql++.bkl] ###



    COND_DEPS_TRACKING_1="#"
    if test "x$DEPS_TRACKING" = "x1" ; then
        COND_DEPS_TRACKING_1=""
    fi
    AC_SUBST(COND_DEPS_TRACKING_1)
dnl ### begin block 20_COND_PLATFORM_MACOSX_0_USE_SOVERCYGWIN_0_USE_SOVERSION_1[./mysql++.bkl] ###
    COND_PLATFORM_MACOSX_0_USE_SOVERCYGWIN_0_USE_SOVERSION_1="#"
    if test "x$PLATFORM_MACOSX" = "x0" -a "x$USE_SOVERCYGWIN" = "x0" -a "x$USE_SOVERSION" = "x1" ; then
        COND_PLATFORM_MACOSX_0_USE_SOVERCYGWIN_0_USE_SOVERSION_1=""
    fi
    AC_SUBST(COND_PLATFORM_MACOSX_0_USE_SOVERCYGWIN_0_USE_SOVERSION_1)
dnl ### begin block 20_COND_PLATFORM_MACOSX_0_USE_SOVERSION_1[./mysql++.bkl] ###


    COND_PLATFORM_MACOSX_0_USE_SOVERSION_1="#"
    if test "x$PLATFORM_MACOSX" = "x0" -a "x$USE_SOVERSION" = "x1" ; then
        COND_PLATFORM_MACOSX_0_USE_SOVERSION_1=""
    fi
    AC_SUBST(COND_PLATFORM_MACOSX_0_USE_SOVERSION_1)
dnl ### begin block 20_COND_PLATFORM_MACOSX_1[./mysql++.bkl] ###


    COND_PLATFORM_MACOSX_1="#"
    if test "x$PLATFORM_MACOSX" = "x1" ; then
        COND_PLATFORM_MACOSX_1=""
    fi
    AC_SUBST(COND_PLATFORM_MACOSX_1)
dnl ### begin block 20_COND_PLATFORM_MACOSX_1_USE_SOVERSION_1[./mysql++.bkl] ###
    COND_PLATFORM_MACOSX_1_USE_SOVERSION_1="#"
    if test "x$PLATFORM_MACOSX" = "x1" -a "x$USE_SOVERSION" = "x1" ; then
        COND_PLATFORM_MACOSX_1_USE_SOVERSION_1=""
    fi



    AC_SUBST(COND_PLATFORM_MACOSX_1_USE_SOVERSION_1)
dnl ### begin block 20_COND_PLATFORM_MAC_0[./mysql++.bkl] ###



    COND_PLATFORM_MAC_0="#"



    if test "x$PLATFORM_MAC" = "x0" ; then


        COND_PLATFORM_MAC_0=""









    fi





    AC_SUBST(COND_PLATFORM_MAC_0)




dnl ### begin block 20_COND_PLATFORM_MAC_1[./mysql++.bkl] ###





    COND_PLATFORM_MAC_1="#"

    if test "x$PLATFORM_MAC" = "x1" ; then
        COND_PLATFORM_MAC_1=""
    fi
    AC_SUBST(COND_PLATFORM_MAC_1)
dnl ### begin block 20_COND_PLATFORM_OS2_1[./mysql++.bkl] ###

    COND_PLATFORM_OS2_1="#"
    if test "x$PLATFORM_OS2" = "x1" ; then
        COND_PLATFORM_OS2_1=""
    fi

    AC_SUBST(COND_PLATFORM_OS2_1)
dnl ### begin block 20_COND_USE_SOSYMLINKS_1[./mysql++.bkl] ###

    COND_USE_SOSYMLINKS_1="#"
    if test "x$USE_SOSYMLINKS" = "x1" ; then
        COND_USE_SOSYMLINKS_1=""








    fi






    AC_SUBST(COND_USE_SOSYMLINKS_1)






dnl ### begin block 20_COND_USE_SOVERCYGWIN_1_USE_SOVERSION_1[./mysql++.bkl] ###








    COND_USE_SOVERCYGWIN_1_USE_SOVERSION_1="#"



    if test "x$USE_SOVERCYGWIN" = "x1" -a "x$USE_SOVERSION" = "x1" ; then

        COND_USE_SOVERCYGWIN_1_USE_SOVERSION_1=""
    fi
    AC_SUBST(COND_USE_SOVERCYGWIN_1_USE_SOVERSION_1)
dnl ### begin block 20_COND_USE_SOVERLINUX_1[./mysql++.bkl] ###
    COND_USE_SOVERLINUX_1="#"

    if test "x$USE_SOVERLINUX" = "x1" ; then



        COND_USE_SOVERLINUX_1=""


    fi

    AC_SUBST(COND_USE_SOVERLINUX_1)

















dnl ### begin block 20_COND_USE_SOVERSION_0[./mysql++.bkl] ###


    COND_USE_SOVERSION_0="#"




    if test "x$USE_SOVERSION" = "x0" ; then


        COND_USE_SOVERSION_0=""
    fi
    AC_SUBST(COND_USE_SOVERSION_0)
dnl ### begin block 20_COND_USE_SOVERSOLARIS_1[./mysql++.bkl] ###

    COND_USE_SOVERSOLARIS_1="#"
    if test "x$USE_SOVERSOLARIS" = "x1" ; then

        COND_USE_SOVERSOLARIS_1=""





    fi






    AC_SUBST(COND_USE_SOVERSOLARIS_1)






dnl ### begin block 20_COND_WINDOWS_IMPLIB_1[./mysql++.bkl] ###






    COND_WINDOWS_IMPLIB_1="#"






    if test "x$WINDOWS_IMPLIB" = "x1" ; then

        COND_WINDOWS_IMPLIB_1=""

    fi
    AC_SUBST(COND_WINDOWS_IMPLIB_1)

Changes to lib/uds_connection.cpp.

1
2



3

4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
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
56


57



58














59






60

61
62
63
64
65
66
67
68
69
70
71
72
73


74







75
76


77
78

79
80
81

82
83
84
85
86
87
88
89











90
91
92
93
94
95
96



97
98
99




100
101
102
103
104
105

106
107
108
109
110
111
112
113



114



115
116






117




118
119

120
/***********************************************************************
 uds_connection.cpp - Implements the UnixDomainSocketConnection class.





 Copyright (c) 2007-2008 by Educational Technology Resources, Inc.
 Others may also hold copyrights on code in this file.  See the
 CREDITS.txt file in the top directory of the distribution for details.

 This file is part of MySQL++.

 MySQL++ is free software; you can redistribute it and/or modify it
 under the terms of the GNU Lesser General Public License as published
 by the Free Software Foundation; either version 2.1 of the License, or
 (at your option) any later version.

 MySQL++ is distributed in the hope that it will be useful, but WITHOUT
 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
 License for more details.

 You should have received a copy of the GNU Lesser General Public
 License along with MySQL++; if not, write to the Free Software
 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
 USA
***********************************************************************/

#define MYSQLPP_NOT_HEADER
#include "common.h"
#include "uds_connection.h"

#include "exceptions.h"

#if !defined(MYSQLPP_PLATFORM_WINDOWS)
#	include <unistd.h>
#	include <sys/stat.h>
#endif

using namespace std;

namespace mysqlpp {






static const char* common_complaint =









		"UnixDomainSocketConnection only works on POSIX systems";























bool
UnixDomainSocketConnection::connect(const char* path,
		const char* db, const char* user, const char* pass)
{
#if !defined(MYSQLPP_PLATFORM_WINDOWS)
	if (is_socket(path, &error_message_)) {
		return Connection::connect(db, path, user, pass);



	}
	(void)common_complaint;
#else
	error_message_ = common_complaint;




#endif



	if (throw_exceptions()) {



		throw ConnectionFailed(error_message_.c_str());














	}






	else {

		return false;
	}
}


bool
UnixDomainSocketConnection::is_socket(const char* path, std::string* error)
{
#if !defined(MYSQLPP_PLATFORM_WINDOWS)
	if (path) {
		struct stat fi;

		if (access(path, F_OK) != 0) {


			if (error) {







				*error = path;
				*error += " does not exist";


			}
		}

		else if (access(path, R_OK | W_OK) != 0) {
			if (error) {
				*error = "Don't have read-write permission for ";

				*error += path;
			}
		}
		else if (stat(path, &fi) != 0) {
			if (error) {
				*error = "Failed to get information for ";
				*error += path;
			}











		}
		else if (!S_ISSOCK(fi.st_mode)) {
			if (error) {
				*error = path;
				*error += " is not a Unix domain socket";
			}
		}



		else {
			// It's a socket, and we have permission to use it
			if (error) {




				error->clear();
			}
			return true;
		}
	}
	else

#endif
	if (error) {
#if !defined(MYSQLPP_PLATFORM_WINDOWS)
		*error = "NULL is not a valid Unix domain socket";
#else
		*error = common_complaint;
#endif
	}







	return false;
}












} // end namespace mysqlpp



|
>
>
>

>
|
|
|



















<
|
|

|

<
|
|
<



|
>
>

>
>
>
|
>
>
>
>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
<
<
<
|
<
|
|
>
>
>
|
<
|
<
>
>
>
>
|
|
>
>
|
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
>
>
>
>
>
|
>
|
|
|
|

<
|
<
<
<
|
|
<
>
>
|
>
>
>
>
>
>
>
|
<
>
>
|
<
>
|
|
|
>
|
|
<
|
|
|
<
|
>
>
>
>
>
>
>
>
>
>
>
|
|
|
<
<
|
<
>
>
>
|
<
|
>
>
>
>
|
<
|
|
<
<
>
|
<
|
|
|
|
<
|
>
>
>
|
>
>
>
|
|
>
>
>
>
>
>
|
>
>
>
>
|
|
>
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
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
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80



81

82
83
84
85
86
87

88

89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
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

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

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
/***********************************************************************
 resetdb.cpp - (Re)initializes the example database, mysql_cpp_data.
	You must run this at least once before running most of the other
	examples, and it is helpful sometimes to run it again, as some of
	the examples modify the table in this database.

 Copyright (c) 1998 by Kevin Atkinson, (c) 1999-2001 by MySQL AB, and
 (c) 2004-2009 by Educational Technology Resources, Inc.  Others may
 also hold copyrights on code in this file.  See the CREDITS file in
 the top directory of the distribution for details.

 This file is part of MySQL++.

 MySQL++ is free software; you can redistribute it and/or modify it
 under the terms of the GNU Lesser General Public License as published
 by the Free Software Foundation; either version 2.1 of the License, or
 (at your option) any later version.

 MySQL++ is distributed in the hope that it will be useful, but WITHOUT
 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
 License for more details.

 You should have received a copy of the GNU Lesser General Public
 License along with MySQL++; if not, write to the Free Software
 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
 USA
***********************************************************************/


#include "cmdline.h"
#include "printdata.h"

#include <mysql++.h>


#include <iostream>
#include <cstdio>


using namespace std;


// Pull in the sample database name from the cmdline module.
extern const char* kpcSampleDatabase;


// Convert a packed version number in the format used within MySQL++
// to a printable string.
static string
version_str(int packed)
{
	char buf[9];
	snprintf(buf, sizeof(buf), "%d.%d.%d",
			(packed & 0xFF0000) >> 16,
			(packed & 0x00FF00) >> 8,
			(packed & 0x0000FF));
	return buf;
}


int
main(int argc, char *argv[])
{
	// Ensure that we're not mixing library and header file versions.
	// This is really easy to do if you have MySQL++ on your system and
	// are trying to build a new version, and run the examples directly
	// instead of through exrun.
	if (mysqlpp::get_library_version() != MYSQLPP_HEADER_VERSION) {
		cerr << "Version mismatch: library is v" <<
				version_str(mysqlpp::get_library_version()) <<
				", headers are v" <<
				version_str(MYSQLPP_HEADER_VERSION) <<
				".  Are you running this" << endl <<
				"with exrun?  See README.examples." << endl;
		return 1;
	}
	
	// Get connection parameters from command line
	mysqlpp::examples::CommandLine cmdline(argc, argv);
	if (!cmdline) {
		return 1;
	}





	// Connect to database server
	mysqlpp::Connection con;
	try {
		if (cmdline.dtest_mode()) {
			cout << "Connecting to database server..." << endl;
		}

		else {

			cout << "Connecting to '" << 
					(cmdline.user() || "USERNAME") << "'@'" <<
					(cmdline.server() || "localhost") << "', with" <<
					(cmdline.pass() && cmdline.pass()[0] ? "" : "out") <<
					" password..." << endl;
		}
		con.connect(0, cmdline.server(), cmdline.user(), cmdline.pass());
	}
	catch (exception& er) {
		cerr << "Connection failed: " << er.what() << endl;
		return 1;
	}
	
	// Create new sample database, or re-create it.  We suppress
	// exceptions, because it's not an error if DB doesn't yet exist.
	bool new_db = false;
	{
		mysqlpp::NoExceptions ne(con);
		mysqlpp::Query query = con.query();
		if (con.select_db(mysqlpp::examples::db_name)) {
			// Toss old tables, ignoring errors because it would just
			// mean the table doesn't exist, which doesn't matter.
			cout << "Dropping existing sample data tables..." << endl;
			query.exec("drop table stock");
			query.exec("drop table images");
			query.exec("drop table deadlock_test1");
			query.exec("drop table deadlock_test2");
		}
		else {
			// Database doesn't exist yet, so create and select it.
			if (con.create_db(mysqlpp::examples::db_name) &&
					con.select_db(mysqlpp::examples::db_name)) {
				new_db = true;
			}
			else {
				cerr << "Error creating DB: " << con.error() << endl;
				return 1;
			}
		}
	}


	// Create sample data table within sample database.



	try {
		// Send the query to create the stock table and execute it.

		cout << "Creating stock table..." << endl;
		mysqlpp::Query query = con.query();
		query << 
				"CREATE TABLE stock (" <<
				"  item CHAR(30) NOT NULL, " <<
				"  num BIGINT NOT NULL, " <<
				"  weight DOUBLE NOT NULL, " <<
				"  price DECIMAL(6,2) NULL, " << // NaN & inf. == NULL
				"  sdate DATE NOT NULL, " <<
				"  description MEDIUMTEXT NULL) " <<
				"ENGINE = InnoDB " <<

				"CHARACTER SET utf8 COLLATE utf8_general_ci";
		query.execute();


		// Set up the template query to insert the data.  The parse()
		// call tells the query object that this is a template and
		// not a literal query string.
		query << "insert into %6:table values " <<
				"(%0q, %1q, %2, %3, %4q, %5q:desc)";
		query.parse();


		// Set a default for template query parameters "table" and "desc".
		query.template_defaults["table"] = "stock";
		query.template_defaults["desc"] = mysqlpp::null;


		// Notice that we don't give a sixth parameter in these calls,
		// so the default value of "stock" is used.  Also notice that
		// the first row is a UTF-8 encoded Unicode string!  All you
		// have to do to store Unicode data in recent versions of MySQL
		// is use UTF-8 encoding.
		cout << "Populating stock table..." << flush;
		query.execute("Nürnberger Brats", 97, 1.5, 8.79, "2005-03-10");
		query.execute("Pickle Relish", 87, 1.5, 1.75, "1998-09-04");
		query.execute("Hot Mustard", 73, .95, .97, "1998-05-25",
				"good American yellow mustard, not that European stuff");
		query.execute("Hotdog Buns", 65, 1.1, 1.1, "1998-04-23");

		// Test that above did what we wanted.
		cout << "inserted " << con.count_rows("stock") << " rows." << endl;




		// Now create empty images table, for testing BLOB and auto-
		// increment column features.
		cout << "Creating empty images table..." << endl;
		query.reset();		// forget template query info

		query << 
				"CREATE TABLE images (" <<
				"  id INT UNSIGNED AUTO_INCREMENT, " <<
				"  data BLOB, " <<
				"  PRIMARY KEY (id)" <<
				")";

		query.execute();



		// Create the tables used by examples/deadlock.cpp
		cout << "Creating deadlock testing tables..." << endl;

		query.execute("CREATE TABLE deadlock_test1 (x INT) ENGINE=innodb");
		query.execute("CREATE TABLE deadlock_test2 (x INT) ENGINE=innodb");
		query.execute("INSERT INTO deadlock_test1 VALUES (1);");
		query.execute("INSERT INTO deadlock_test2 VALUES (2);");


		// Report success
		cout << (new_db ? "Created" : "Reinitialized") <<
				" sample database successfully." << endl;
	}
	catch (const mysqlpp::BadQuery& er) {
		// Handle any query errors
		cerr << endl << "Query error: " << er.what() << endl;
		return 1;
	}
	catch (const mysqlpp::BadConversion& er) {
		// Handle bad conversions
		cerr << endl << "Conversion error: " << er.what() << endl <<
				"\tretrieved data size: " << er.retrieved <<
				", actual size: " << er.actual_size << endl;
		return 1;
	}
	catch (const mysqlpp::Exception& er) {
		// Catch-all for any other MySQL++ exceptions
		cerr << endl << "Error: " << er.what() << endl;
		return 1;
	}

	return 0;
}

Changes to lib/uds_connection.h.



1
2
3
4

5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
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
56
57
58
59
60
61
62
63
64




65
66
67
68
69
70
71
72
73













74
75
76
77
78
79
80
81
82
83
84
85

86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118


/// \file uds_connection.h
/// \brief Declares the UnixDomainSocketConnection class.

/***********************************************************************

 Copyright (c) 2007-2008 by Educational Technology Resources, Inc.
 Others may also hold copyrights on code in this file.  See the
 CREDITS.txt file in the top directory of the distribution for details.

 This file is part of MySQL++.

 MySQL++ is free software; you can redistribute it and/or modify it
 under the terms of the GNU Lesser General Public License as published
 by the Free Software Foundation; either version 2.1 of the License, or
 (at your option) any later version.

 MySQL++ is distributed in the hope that it will be useful, but WITHOUT
 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
 License for more details.

 You should have received a copy of the GNU Lesser General Public
 License along with MySQL++; if not, write to the Free Software
 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
 USA
***********************************************************************/

#if !defined(MYSQLPP_UDS_CONNECTION_H)
#define MYSQLPP_UDS_CONNECTION_H

#include "connection.h"

namespace mysqlpp {

/// \brief Specialization of \c Connection for Unix domain sockets
///
/// This class just simplifies the connection creation interface of
/// \c Connection.  It does not add new functionality.

class UnixDomainSocketConnection : public Connection
{
public:
	/// \brief Create object without connecting it to the MySQL server.
	UnixDomainSocketConnection() :
	Connection()

	{

	}

	/// \brief Create object and connect to database server over Unix
	/// domain sockets in one step.
	///
	/// \param path filesystem path to socket
	/// \param db name of database to use
	/// \param user user name to log in under, or 0 to use the user
	///		name the program is running under
	/// \param password password to use when logging in
	///
	/// \b BEWARE: These parameters are not in the same order as those
	/// in the corresponding constructor for Connection.  This is a
	/// feature, not a bug. :)
	UnixDomainSocketConnection(const char* path, const char* db = 0,
			const char* user = 0, const char* password = 0) :
	Connection()
	{
		connect(path, db, user, password);




	}

	/// \brief Establish a new connection using the same parameters as
	/// an existing connection.
	///
	/// \param other pre-existing connection to clone
	UnixDomainSocketConnection(const UnixDomainSocketConnection& other) :
	Connection(other)
	{













	}

	/// \brief Destroy object
	~UnixDomainSocketConnection() { }

	/// \brief Connect to database after object is created.
	///
	/// It's better to use the connect-on-create constructor if you can.
	/// See its documentation for the meaning of these parameters.
	///
	/// If you call this method on an object that is already connected
	/// to a database server, the previous connection is dropped and a

	/// new connection is established.
	bool connect(const char* path, const char* db = 0,
			const char* user = 0, const char* password = 0);

	/// \brief Check that the given path names a Unix domain socket and
	/// that we have read-write permission for it
	///
	/// \param path the filesystem path to the socket
	/// \param error on failure, reason is placed here; take default
	/// if you do not need a reason if it fails
	///
	/// \return false if address fails to pass sanity checks
	static bool is_socket(const char* path, std::string* error = 0);

private:
	/// \brief Provide uncallable versions of the parent class ctors we
	/// don't want to provide so we don't get warnings about hidden
	/// overloads with some compilers
	UnixDomainSocketConnection(bool) { }
	UnixDomainSocketConnection(const char*, const char*, const char*,
			const char*, unsigned int) { }

	/// \brief Explicitly override parent class version so we don't get
	/// complaints about hidden overloads with some compilers
	bool connect(const char*, const char*, const char*, const char*,
			unsigned int) { return false; }
};


} // end namespace mysqlpp

#endif // !defined(MYSQLPP_UDS_CONNECTION_H)

>
>
|
<

<
>
|
|
|



















<
<
<
|
|
<

<
<
<
<
|
<
|
<
<
<
|
>
|
>
|
|
<
|
<
<
<
<
<
<
<
<
<
<
<
<
<
|
<
>
>
>
>

<
<
<
<
<
<
<
|
>
>
>
>
>
>
>
>
>
>
>
>
>
|
|
<
<
|
<
<
<
<
<
<
<
>
|
<
<
|
<
<
<
<
<
<
<
<
<

|
<
<
<
<
<
<
|
<
<
<
|
<
|
|
<
|
<
|
1
2
3

4

5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27



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
56
57
58
59
60
61


62







63
64


65









66
67






68



69

70
71

72

73
/***********************************************************************
 simple1.cpp - Example showing the simplest way to get data from a MySQL
	table with MySQL++.



 Copyright (c) 1998 by Kevin Atkinson, (c) 1999-2001 by MySQL AB, and
 (c) 2004-2009 by Educational Technology Resources, Inc.  Others may
 also hold copyrights on code in this file.  See the CREDITS.txt file
 in the top directory of the distribution for details.

 This file is part of MySQL++.

 MySQL++ is free software; you can redistribute it and/or modify it
 under the terms of the GNU Lesser General Public License as published
 by the Free Software Foundation; either version 2.1 of the License, or
 (at your option) any later version.

 MySQL++ is distributed in the hope that it will be useful, but WITHOUT
 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
 License for more details.

 You should have received a copy of the GNU Lesser General Public
 License along with MySQL++; if not, write to the Free Software
 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
 USA
***********************************************************************/




#include "cmdline.h"
#include "printdata.h"






#include <mysql++.h>





#include <iostream>
#include <iomanip>

using namespace std;

int

main(int argc, char *argv[])













{

	// Get database access parameters from command line
	mysqlpp::examples::CommandLine cmdline(argc, argv);
	if (!cmdline) {
		return 1;
	}








	// Connect to the sample database.
	mysqlpp::Connection conn(false);
	if (conn.connect(mysqlpp::examples::db_name, cmdline.server(),
			cmdline.user(), cmdline.pass())) {
		// Retrieve a subset of the sample stock table set up by resetdb
		// and display it.
		mysqlpp::Query query = conn.query("select item from stock");
		if (mysqlpp::StoreQueryResult res = query.store()) {
			cout << "We have:" << endl;
			mysqlpp::StoreQueryResult::const_iterator it;
			for (it = res.begin(); it != res.end(); ++it) {
				mysqlpp::Row row = *it;
				cout << '\t' << row[0] << endl;
			}
		}


		else {







			cerr << "Failed to get item list: " << query.error() << endl;
			return 1;


		}










		return 0;






	}



	else {

		cerr << "DB connection failed: " << conn.error() << endl;
		return 1;

	}

}

Changes to lib/utility.cpp.


1









2






































































































3

4



5

6










































































































7

8











































































































9

10








11

12



13
































































































14

15



16

17


18






































































































































































































































































































































19


20

21



22

23



24



































































































25

26


















































































































































































































































































































































27

28



29

30



31

32



33

34


35





















































































36

















































































































37




38

39



40



41

42






























































































43

44



45





46

47




















































































































































































































/***********************************************************************









 utility.cpp - Implements utility functions used within the library.








































































































 Copyright (c) 2009 by Warren Young.  Others may also hold copyrights



 on code in this file.  See the CREDITS file in the top directory of

 the distribution for details.












































































































 This file is part of MySQL++.













































































































 MySQL++ is free software; you can redistribute it and/or modify it








 under the terms of the GNU Lesser General Public License as published

 by the Free Software Foundation; either version 2.1 of the License, or



 (at your option) any later version.


































































































 MySQL++ is distributed in the hope that it will be useful, but WITHOUT



 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or

 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public


 License for more details.









































































































































































































































































































































 You should have received a copy of the GNU Lesser General Public

 License along with MySQL++; if not, write to the Free Software



 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301

 USA



***********************************************************************/





































































































#include "utility.h"




















































































































































































































































































































































namespace mysqlpp {



	namespace internal {

		void str_to_lwr(std::string& s)



		{

			std::string::iterator it;



			for (it = s.begin(); it != s.end(); ++it) {

				*it = tolower(*it);


			}





















































































		}






















































































































		void str_to_lwr(std::string& ls, const char* mcs)

		{



			ls.reserve(strlen(mcs));



			while (mcs && *mcs) {

				ls += tolower(*mcs++);






























































































			}

		}



	} // end namespace internal





} // end namespace mysqlpp





















































































































































































































>
|
>
>
>
>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

>
|
>
>
>
|
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

>
|
>
>
>
>
>
>
>
>
|
>
|
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

>
|
>
>
>
|
>
|
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

>
>
|
>
|
>
>
>
|
>
|
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

>
|
>
>
>
|
>
|
>
>
>
|
>
|
>
>
>
|
>
|
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

>
>
>
>
|
>
|
>
>
>
|
>
>
>
|
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
|
>
>
>
|
>
>
>
>
>
|
>

>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
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
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
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
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
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
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
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
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
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
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
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
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
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
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
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
1694
1695
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
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
# Doxyfile 1.8.2

# This file describes the settings to be used by the documentation system
# doxygen (www.doxygen.org) for a project.
#
# All text after a hash (#) is considered a comment and will be ignored.
# The format is:
#       TAG = value [value, ...]
# For lists items can also be appended using:
#       TAG += value [value, ...]
# Values that contain spaces should be placed between quotes (" ").

#---------------------------------------------------------------------------
# Project related configuration options
#---------------------------------------------------------------------------

# This tag specifies the encoding used for all characters in the config file
# that follow. The default is UTF-8 which is also the encoding used for all
# text before the first occurrence of this tag. Doxygen uses libiconv (or the
# iconv built into libc) for the transcoding. See
# http://www.gnu.org/software/libiconv for the list of possible encodings.

DOXYFILE_ENCODING      = UTF-8

# The PROJECT_NAME tag is a single word (or sequence of words) that should
# identify the project. Note that if you do not use Doxywizard you need
# to put quotes around the project name if it contains spaces.

PROJECT_NAME           = "MySQL++ SSQLS v2 Translator"

# The PROJECT_NUMBER tag can be used to enter a project or revision number.
# This could be handy for archiving the generated documentation or
# if some version control system is used.

PROJECT_NUMBER         = @PACKAGE_VERSION@

# Using the PROJECT_BRIEF tag one can provide an optional one line description
# for a project that appears at the top of each page and should give viewer
# a quick idea about the purpose of the project. Keep the description short.

PROJECT_BRIEF          =

# With the PROJECT_LOGO tag one can specify an logo or icon that is
# included in the documentation. The maximum height of the logo should not
# exceed 55 pixels and the maximum width should not exceed 200 pixels.
# Doxygen will copy the logo to the output directory.

PROJECT_LOGO           =

# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute)
# base path where the generated documentation will be put.
# If a relative path is entered, it will be relative to the location
# where doxygen was started. If left blank the current directory will be used.

OUTPUT_DIRECTORY       = ../doc

# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create
# 4096 sub-directories (in 2 levels) under the output directory of each output
# format and will distribute the generated files over these directories.
# Enabling this option can be useful when feeding doxygen a huge amount of
# source files, where putting all generated files in the same directory would
# otherwise cause performance problems for the file system.

CREATE_SUBDIRS         = NO

# The OUTPUT_LANGUAGE tag is used to specify the language in which all
# documentation generated by doxygen is written. Doxygen will use this
# information to generate all constant output in the proper language.
# The default language is English, other supported languages are:
# Afrikaans, Arabic, Brazilian, Catalan, Chinese, Chinese-Traditional,
# Croatian, Czech, Danish, Dutch, Esperanto, Farsi, Finnish, French, German,
# Greek, Hungarian, Italian, Japanese, Japanese-en (Japanese with English
# messages), Korean, Korean-en, Lithuanian, Norwegian, Macedonian, Persian,
# Polish, Portuguese, Romanian, Russian, Serbian, Serbian-Cyrillic, Slovak,
# Slovene, Spanish, Swedish, Ukrainian, and Vietnamese.

OUTPUT_LANGUAGE        = English

# If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will
# include brief member descriptions after the members that are listed in
# the file and class documentation (similar to JavaDoc).
# Set to NO to disable this.

BRIEF_MEMBER_DESC      = YES

# If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend
# the brief description of a member or function before the detailed description.
# Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the
# brief descriptions will be completely suppressed.

REPEAT_BRIEF           = YES

# This tag implements a quasi-intelligent brief description abbreviator
# that is used to form the text in various listings. Each string
# in this list, if found as the leading text of the brief description, will be
# stripped from the text and the result after processing the whole list, is
# used as the annotated text. Otherwise, the brief description is used as-is.
# If left blank, the following values are used ("$name" is automatically
# replaced with the name of the entity): "The $name class" "The $name widget"
# "The $name file" "is" "provides" "specifies" "contains"
# "represents" "a" "an" "the"

ABBREVIATE_BRIEF       =

# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then
# Doxygen will generate a detailed section even if there is only a brief
# description.

ALWAYS_DETAILED_SEC    = NO

# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all
# inherited members of a class in the documentation of that class as if those
# members were ordinary class members. Constructors, destructors and assignment
# operators of the base classes will not be shown.

INLINE_INHERITED_MEMB  = NO

# If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full
# path before files name in the file list and in the header files. If set
# to NO the shortest path that makes the file name unique will be used.

FULL_PATH_NAMES        = NO

# If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag
# can be used to strip a user-defined part of the path. Stripping is
# only done if one of the specified strings matches the left-hand part of
# the path. The tag can be used to show relative paths in the file list.
# If left blank the directory from which doxygen is run is used as the
# path to strip. Note that you specify absolute paths here, but also
# relative paths, which will be relative from the directory where doxygen is
# started.

STRIP_FROM_PATH        =

# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of
# the path mentioned in the documentation of a class, which tells
# the reader which header file to include in order to use a class.
# If left blank only the name of the header file containing the class
# definition is used. Otherwise one should specify the include paths that
# are normally passed to the compiler using the -I flag.

STRIP_FROM_INC_PATH    =

# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter
# (but less readable) file names. This can be useful if your file system
# doesn't support long names like on DOS, Mac, or CD-ROM.

SHORT_NAMES            = NO

# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen
# will interpret the first line (until the first dot) of a JavaDoc-style
# comment as the brief description. If set to NO, the JavaDoc
# comments will behave just like regular Qt-style comments
# (thus requiring an explicit @brief command for a brief description.)

JAVADOC_AUTOBRIEF      = NO

# If the QT_AUTOBRIEF tag is set to YES then Doxygen will
# interpret the first line (until the first dot) of a Qt-style
# comment as the brief description. If set to NO, the comments
# will behave just like regular Qt-style comments (thus requiring
# an explicit \brief command for a brief description.)

QT_AUTOBRIEF           = NO

# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen
# treat a multi-line C++ special comment block (i.e. a block of //! or ///
# comments) as a brief description. This used to be the default behaviour.
# The new default is to treat a multi-line C++ comment block as a detailed
# description. Set this tag to YES if you prefer the old behaviour instead.

MULTILINE_CPP_IS_BRIEF = NO

# If the INHERIT_DOCS tag is set to YES (the default) then an undocumented
# member inherits the documentation from any documented member that it
# re-implements.

INHERIT_DOCS           = YES

# If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce
# a new page for each member. If set to NO, the documentation of a member will
# be part of the file/class/namespace that contains it.

SEPARATE_MEMBER_PAGES  = NO

# The TAB_SIZE tag can be used to set the number of spaces in a tab.
# Doxygen uses this value to replace tabs by spaces in code fragments.

TAB_SIZE               = 4

# This tag can be used to specify a number of aliases that acts
# as commands in the documentation. An alias has the form "name=value".
# For example adding "sideeffect=\par Side Effects:\n" will allow you to
# put the command \sideeffect (or @sideeffect) in the documentation, which
# will result in a user-defined paragraph with heading "Side Effects:".
# You can put \n's in the value part of an alias to insert newlines.

ALIASES                =

# This tag can be used to specify a number of word-keyword mappings (TCL only).
# A mapping has the form "name=value". For example adding
# "class=itcl::class" will allow you to use the command class in the
# itcl::class meaning.

TCL_SUBST              =

# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C
# sources only. Doxygen will then generate output that is more tailored for C.
# For instance, some of the names that are used will be different. The list
# of all members will be omitted, etc.

OPTIMIZE_OUTPUT_FOR_C  = NO

# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java
# sources only. Doxygen will then generate output that is more tailored for
# Java. For instance, namespaces will be presented as packages, qualified
# scopes will look different, etc.

OPTIMIZE_OUTPUT_JAVA   = NO

# Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran
# sources only. Doxygen will then generate output that is more tailored for
# Fortran.

OPTIMIZE_FOR_FORTRAN   = NO

# Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL
# sources. Doxygen will then generate output that is tailored for
# VHDL.

OPTIMIZE_OUTPUT_VHDL   = NO

# Doxygen selects the parser to use depending on the extension of the files it
# parses. With this tag you can assign which parser to use for a given
# extension. Doxygen has a built-in mapping, but you can override or extend it
# using this tag. The format is ext=language, where ext is a file extension,
# and language is one of the parsers supported by doxygen: IDL, Java,
# Javascript, CSharp, C, C++, D, PHP, Objective-C, Python, Fortran, VHDL, C,
# C++. For instance to make doxygen treat .inc files as Fortran files (default
# is PHP), and .f files as C (default is Fortran), use: inc=Fortran f=C. Note
# that for custom extensions you also need to set FILE_PATTERNS otherwise the
# files are not read by doxygen.

EXTENSION_MAPPING      =

# If MARKDOWN_SUPPORT is enabled (the default) then doxygen pre-processes all
# comments according to the Markdown format, which allows for more readable
# documentation. See http://daringfireball.net/projects/markdown/ for details.
# The output of markdown processing is further processed by doxygen, so you
# can mix doxygen, HTML, and XML commands with Markdown formatting.
# Disable only in case of backward compatibilities issues.

MARKDOWN_SUPPORT       = YES

# When enabled doxygen tries to link words that correspond to documented classes,
# or namespaces to their corresponding documentation. Such a link can be
# prevented in individual cases by by putting a % sign in front of the word or
# globally by setting AUTOLINK_SUPPORT to NO.

AUTOLINK_SUPPORT       = YES

# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want
# to include (a tag file for) the STL sources as input, then you should
# set this tag to YES in order to let doxygen match functions declarations and
# definitions whose arguments contain STL classes (e.g. func(std::string); v.s.
# func(std::string) {}). This also makes the inheritance and collaboration
# diagrams that involve STL classes more complete and accurate.

BUILTIN_STL_SUPPORT    = NO

# If you use Microsoft's C++/CLI language, you should set this option to YES to
# enable parsing support.

CPP_CLI_SUPPORT        = NO

# Set the SIP_SUPPORT tag to YES if your project consists of sip sources only.
# Doxygen will parse them like normal C++ but will assume all classes use public
# instead of private inheritance when no explicit protection keyword is present.

SIP_SUPPORT            = NO

# For Microsoft's IDL there are propget and propput attributes to indicate getter and setter methods for a property. Setting this option to YES (the default) will make doxygen replace the get and set methods by a property in the documentation. This will only work if the methods are indeed getting or setting a simple type. If this is not the case, or you want to show the methods anyway, you should set this option to NO.

IDL_PROPERTY_SUPPORT   = YES

# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC
# tag is set to YES, then doxygen will reuse the documentation of the first
# member in the group (if any) for the other members of the group. By default
# all members of a group must be documented explicitly.

DISTRIBUTE_GROUP_DOC   = NO

# Set the SUBGROUPING tag to YES (the default) to allow class member groups of
# the same type (for instance a group of public functions) to be put as a
# subgroup of that type (e.g. under the Public Functions section). Set it to
# NO to prevent subgrouping. Alternatively, this can be done per class using
# the \nosubgrouping command.

SUBGROUPING            = NO

# When the INLINE_GROUPED_CLASSES tag is set to YES, classes, structs and
# unions are shown inside the group in which they are included (e.g. using
# @ingroup) instead of on a separate page (for HTML and Man pages) or
# section (for LaTeX and RTF).

INLINE_GROUPED_CLASSES = NO

# When the INLINE_SIMPLE_STRUCTS tag is set to YES, structs, classes, and
# unions with only public data fields will be shown inline in the documentation
# of the scope in which they are defined (i.e. file, namespace, or group
# documentation), provided this scope is documented. If set to NO (the default),
# structs, classes, and unions are shown on a separate page (for HTML and Man
# pages) or section (for LaTeX and RTF).

INLINE_SIMPLE_STRUCTS  = NO

# When TYPEDEF_HIDES_STRUCT is enabled, a typedef of a struct, union, or enum
# is documented as struct, union, or enum with the name of the typedef. So
# typedef struct TypeS {} TypeT, will appear in the documentation as a struct
# with name TypeT. When disabled the typedef will appear as a member of a file,
# namespace, or class. And the struct will be named TypeS. This can typically
# be useful for C code in case the coding convention dictates that all compound
# types are typedef'ed and only the typedef is referenced, never the tag name.

TYPEDEF_HIDES_STRUCT   = NO

# The SYMBOL_CACHE_SIZE determines the size of the internal cache use to
# determine which symbols to keep in memory and which to flush to disk.
# When the cache is full, less often used symbols will be written to disk.
# For small to medium size projects (<1000 input files) the default value is
# probably good enough. For larger projects a too small cache size can cause
# doxygen to be busy swapping symbols to and from disk most of the time
# causing a significant performance penalty.
# If the system has enough physical memory increasing the cache will improve the
# performance by keeping more symbols in memory. Note that the value works on
# a logarithmic scale so increasing the size by one will roughly double the
# memory usage. The cache size is given by this formula:
# 2^(16+SYMBOL_CACHE_SIZE). The valid range is 0..9, the default is 0,
# corresponding to a cache size of 2^16 = 65536 symbols.

SYMBOL_CACHE_SIZE      = 0

# Similar to the SYMBOL_CACHE_SIZE the size of the symbol lookup cache can be
# set using LOOKUP_CACHE_SIZE. This cache is used to resolve symbols given
# their name and scope. Since this can be an expensive process and often the
# same symbol appear multiple times in the code, doxygen keeps a cache of
# pre-resolved symbols. If the cache is too small doxygen will become slower.
# If the cache is too large, memory is wasted. The cache size is given by this
# formula: 2^(16+LOOKUP_CACHE_SIZE). The valid range is 0..9, the default is 0,
# corresponding to a cache size of 2^16 = 65536 symbols.

LOOKUP_CACHE_SIZE      = 0

#---------------------------------------------------------------------------
# Build related configuration options
#---------------------------------------------------------------------------

# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in
# documentation are documented, even if no documentation was available.
# Private class members and static file members will be hidden unless
# the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES

EXTRACT_ALL            = NO

# If the EXTRACT_PRIVATE tag is set to YES all private members of a class
# will be included in the documentation.

EXTRACT_PRIVATE        = NO

# If the EXTRACT_PACKAGE tag is set to YES all members with package or internal
# scope will be included in the documentation.

EXTRACT_PACKAGE        = NO

# If the EXTRACT_STATIC tag is set to YES all static members of a file
# will be included in the documentation.

EXTRACT_STATIC         = NO

# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs)
# defined locally in source files will be included in the documentation.
# If set to NO only classes defined in header files are included.

EXTRACT_LOCAL_CLASSES  = YES

# This flag is only useful for Objective-C code. When set to YES local
# methods, which are defined in the implementation section but not in
# the interface are included in the documentation.
# If set to NO (the default) only methods in the interface are included.

EXTRACT_LOCAL_METHODS  = NO

# If this flag is set to YES, the members of anonymous namespaces will be
# extracted and appear in the documentation as a namespace called
# 'anonymous_namespace{file}', where file will be replaced with the base
# name of the file that contains the anonymous namespace. By default
# anonymous namespaces are hidden.

EXTRACT_ANON_NSPACES   = NO

# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all
# undocumented members of documented classes, files or namespaces.
# If set to NO (the default) these members will be included in the
# various overviews, but no documentation section is generated.
# This option has no effect if EXTRACT_ALL is enabled.

HIDE_UNDOC_MEMBERS     = YES

# If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all
# undocumented classes that are normally visible in the class hierarchy.
# If set to NO (the default) these classes will be included in the various
# overviews. This option has no effect if EXTRACT_ALL is enabled.

HIDE_UNDOC_CLASSES     = NO

# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all
# friend (class|struct|union) declarations.
# If set to NO (the default) these declarations will be included in the
# documentation.

HIDE_FRIEND_COMPOUNDS  = NO

# If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any
# documentation blocks found inside the body of a function.
# If set to NO (the default) these blocks will be appended to the
# function's detailed documentation block.

HIDE_IN_BODY_DOCS      = NO

# The INTERNAL_DOCS tag determines if documentation
# that is typed after a \internal command is included. If the tag is set
# to NO (the default) then the documentation will be excluded.
# Set it to YES to include the internal documentation.

INTERNAL_DOCS          = NO

# If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate
# file names in lower-case letters. If set to YES upper-case letters are also
# allowed. This is useful if you have classes or files whose names only differ
# in case and if your file system supports case sensitive file names. Windows
# and Mac users are advised to set this option to NO.

CASE_SENSE_NAMES       = YES

# If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen
# will show members with their full class and namespace scopes in the
# documentation. If set to YES the scope will be hidden.

HIDE_SCOPE_NAMES       = NO

# If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen
# will put a list of the files that are included by a file in the documentation
# of that file.

SHOW_INCLUDE_FILES     = YES

# If the FORCE_LOCAL_INCLUDES tag is set to YES then Doxygen
# will list include files with double quotes in the documentation
# rather than with sharp brackets.

FORCE_LOCAL_INCLUDES   = NO

# If the INLINE_INFO tag is set to YES (the default) then a tag [inline]
# is inserted in the documentation for inline members.

INLINE_INFO            = YES

# If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen
# will sort the (detailed) documentation of file and class members
# alphabetically by member name. If set to NO the members will appear in
# declaration order.

SORT_MEMBER_DOCS       = YES

# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the
# brief documentation of file, namespace and class members alphabetically
# by member name. If set to NO (the default) the members will appear in
# declaration order.

SORT_BRIEF_DOCS        = NO

# If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen
# will sort the (brief and detailed) documentation of class members so that
# constructors and destructors are listed first. If set to NO (the default)
# the constructors will appear in the respective orders defined by
# SORT_MEMBER_DOCS and SORT_BRIEF_DOCS.
# This tag will be ignored for brief docs if SORT_BRIEF_DOCS is set to NO
# and ignored for detailed docs if SORT_MEMBER_DOCS is set to NO.

SORT_MEMBERS_CTORS_1ST = NO

# If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the
# hierarchy of group names into alphabetical order. If set to NO (the default)
# the group names will appear in their defined order.

SORT_GROUP_NAMES       = NO

# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be
# sorted by fully-qualified names, including namespaces. If set to
# NO (the default), the class list will be sorted only by class name,
# not including the namespace part.
# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES.
# Note: This option applies only to the class list, not to the
# alphabetical list.

SORT_BY_SCOPE_NAME     = NO

# If the STRICT_PROTO_MATCHING option is enabled and doxygen fails to
# do proper type resolution of all parameters of a function it will reject a
# match between the prototype and the implementation of a member function even
# if there is only one candidate or it is obvious which candidate to choose
# by doing a simple string match. By disabling STRICT_PROTO_MATCHING doxygen
# will still accept a match between prototype and implementation in such cases.

STRICT_PROTO_MATCHING  = NO

# The GENERATE_TODOLIST tag can be used to enable (YES) or
# disable (NO) the todo list. This list is created by putting \todo
# commands in the documentation.

GENERATE_TODOLIST      = YES

# The GENERATE_TESTLIST tag can be used to enable (YES) or
# disable (NO) the test list. This list is created by putting \test
# commands in the documentation.

GENERATE_TESTLIST      = YES

# The GENERATE_BUGLIST tag can be used to enable (YES) or
# disable (NO) the bug list. This list is created by putting \bug
# commands in the documentation.

GENERATE_BUGLIST       = YES

# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or
# disable (NO) the deprecated list. This list is created by putting
# \deprecated commands in the documentation.

GENERATE_DEPRECATEDLIST= YES

# The ENABLED_SECTIONS tag can be used to enable conditional
# documentation sections, marked by \if sectionname ... \endif.

ENABLED_SECTIONS       =

# The MAX_INITIALIZER_LINES tag determines the maximum number of lines
# the initial value of a variable or macro consists of for it to appear in
# the documentation. If the initializer consists of more lines than specified
# here it will be hidden. Use a value of 0 to hide initializers completely.
# The appearance of the initializer of individual variables and macros in the
# documentation can be controlled using \showinitializer or \hideinitializer
# command in the documentation regardless of this setting.

MAX_INITIALIZER_LINES  = 30

# Set the SHOW_USED_FILES tag to NO to disable the list of files generated
# at the bottom of the documentation of classes and structs. If set to YES the
# list will mention the files that were used to generate the documentation.

SHOW_USED_FILES        = YES

# Set the SHOW_FILES tag to NO to disable the generation of the Files page.
# This will remove the Files entry from the Quick Index and from the
# Folder Tree View (if specified). The default is YES.

SHOW_FILES             = YES

# Set the SHOW_NAMESPACES tag to NO to disable the generation of the
# Namespaces page.
# This will remove the Namespaces entry from the Quick Index
# and from the Folder Tree View (if specified). The default is YES.

SHOW_NAMESPACES        = YES

# The FILE_VERSION_FILTER tag can be used to specify a program or script that
# doxygen should invoke to get the current version for each file (typically from
# the version control system). Doxygen will invoke the program by executing (via
# popen()) the command <command> <input-file>, where <command> is the value of
# the FILE_VERSION_FILTER tag, and <input-file> is the name of an input file
# provided by doxygen. Whatever the program writes to standard output
# is used as the file version. See the manual for examples.

FILE_VERSION_FILTER    =

# The LAYOUT_FILE tag can be used to specify a layout file which will be parsed
# by doxygen. The layout file controls the global structure of the generated
# output files in an output format independent way. To create the layout file
# that represents doxygen's defaults, run doxygen with the -l option.
# You can optionally specify a file name after the option, if omitted
# DoxygenLayout.xml will be used as the name of the layout file.

LAYOUT_FILE            =

# The CITE_BIB_FILES tag can be used to specify one or more bib files
# containing the references data. This must be a list of .bib files. The
# .bib extension is automatically appended if omitted. Using this command
# requires the bibtex tool to be installed. See also
# http://en.wikipedia.org/wiki/BibTeX for more info. For LaTeX the style
# of the bibliography can be controlled using LATEX_BIB_STYLE. To use this
# feature you need bibtex and perl available in the search path.

CITE_BIB_FILES         =

#---------------------------------------------------------------------------
# configuration options related to warning and progress messages
#---------------------------------------------------------------------------

# The QUIET tag can be used to turn on/off the messages that are generated
# by doxygen. Possible values are YES and NO. If left blank NO is used.

QUIET                  = NO

# The WARNINGS tag can be used to turn on/off the warning messages that are
# generated by doxygen. Possible values are YES and NO. If left blank
# NO is used.

WARNINGS               = YES

# If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings
# for undocumented members. If EXTRACT_ALL is set to YES then this flag will
# automatically be disabled.

WARN_IF_UNDOCUMENTED   = YES

# If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for
# potential errors in the documentation, such as not documenting some
# parameters in a documented function, or documenting parameters that
# don't exist or using markup commands wrongly.

WARN_IF_DOC_ERROR      = YES

# The WARN_NO_PARAMDOC option can be enabled to get warnings for
# functions that are documented, but have no documentation for their parameters
# or return value. If set to NO (the default) doxygen will only warn about
# wrong or incomplete parameter documentation, but not about the absence of
# documentation.

WARN_NO_PARAMDOC       = NO

# The WARN_FORMAT tag determines the format of the warning messages that
# doxygen can produce. The string should contain the $file, $line, and $text
# tags, which will be replaced by the file and line number from which the
# warning originated and the warning text. Optionally the format may contain
# $version, which will be replaced by the version of the file (if it could
# be obtained via FILE_VERSION_FILTER)

WARN_FORMAT            = "$file:$line: $text"

# The WARN_LOGFILE tag can be used to specify a file to which warning
# and error messages should be written. If left blank the output is written
# to stderr.

WARN_LOGFILE           =

#---------------------------------------------------------------------------
# configuration options related to the input files
#---------------------------------------------------------------------------

# The INPUT tag can be used to specify the files and/or directories that contain
# documented source files. You may enter file names like "myfile.cpp" or
# directories like "/usr/src/myproject". Separate the files or directories
# with spaces.

INPUT                  =

# This tag can be used to specify the character encoding of the source files
# that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is
# also the default input encoding. Doxygen uses libiconv (or the iconv built
# into libc) for the transcoding. See http://www.gnu.org/software/libiconv for
# the list of possible encodings.

INPUT_ENCODING         = UTF-8

# If the value of the INPUT tag contains directories, you can use the
# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp
# and *.h) to filter out the source-files in the directories. If left
# blank the following patterns are tested:
# *.c *.cc *.cxx *.cpp *.c++ *.d *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh
# *.hxx *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm *.dox *.py
# *.f90 *.f *.for *.vhd *.vhdl

FILE_PATTERNS          =

# The RECURSIVE tag can be used to turn specify whether or not subdirectories
# should be searched for input files as well. Possible values are YES and NO.
# If left blank NO is used.

RECURSIVE              = NO

# The EXCLUDE tag can be used to specify files and/or directories that should be
# excluded from the INPUT source files. This way you can easily exclude a
# subdirectory from a directory tree whose root is specified with the INPUT tag.
# Note that relative paths are relative to the directory from which doxygen is
# run.

EXCLUDE                =

# The EXCLUDE_SYMLINKS tag can be used to select whether or not files or
# directories that are symbolic links (a Unix file system feature) are excluded
# from the input.

EXCLUDE_SYMLINKS       = NO

# If the value of the INPUT tag contains directories, you can use the
# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude
# certain files from those directories. Note that the wildcards are matched
# against the file with absolute path, so to exclude all test directories
# for example use the pattern */test/*

EXCLUDE_PATTERNS       =

# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names
# (namespaces, classes, functions, etc.) that should be excluded from the
# output. The symbol name can be a fully qualified name, a word, or if the
# wildcard * is used, a substring. Examples: ANamespace, AClass,
# AClass::ANamespace, ANamespace::*Test

EXCLUDE_SYMBOLS        =

# The EXAMPLE_PATH tag can be used to specify one or more files or
# directories that contain example code fragments that are included (see
# the \include command).

EXAMPLE_PATH           =

# If the value of the EXAMPLE_PATH tag contains directories, you can use the
# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp
# and *.h) to filter out the source-files in the directories. If left
# blank all files are included.

EXAMPLE_PATTERNS       =

# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be
# searched for input files to be used with the \include or \dontinclude
# commands irrespective of the value of the RECURSIVE tag.
# Possible values are YES and NO. If left blank NO is used.

EXAMPLE_RECURSIVE      = NO

# The IMAGE_PATH tag can be used to specify one or more files or
# directories that contain image that are included in the documentation (see
# the \image command).

IMAGE_PATH             =

# The INPUT_FILTER tag can be used to specify a program that doxygen should
# invoke to filter for each input file. Doxygen will invoke the filter program
# by executing (via popen()) the command <filter> <input-file>, where <filter>
# is the value of the INPUT_FILTER tag, and <input-file> is the name of an
# input file. Doxygen will then use the output that the filter program writes
# to standard output.
# If FILTER_PATTERNS is specified, this tag will be
# ignored.

INPUT_FILTER           =

# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern
# basis.
# Doxygen will compare the file name with each pattern and apply the
# filter if there is a match.
# The filters are a list of the form:
# pattern=filter (like *.cpp=my_cpp_filter). See INPUT_FILTER for further
# info on how filters are used. If FILTER_PATTERNS is empty or if
# non of the patterns match the file name, INPUT_FILTER is applied.

FILTER_PATTERNS        =

# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using
# INPUT_FILTER) will be used to filter the input files when producing source
# files to browse (i.e. when SOURCE_BROWSER is set to YES).

FILTER_SOURCE_FILES    = NO

# The FILTER_SOURCE_PATTERNS tag can be used to specify source filters per file
# pattern. A pattern will override the setting for FILTER_PATTERN (if any)
# and it is also possible to disable source filtering for a specific pattern
# using *.ext= (so without naming a filter). This option only has effect when
# FILTER_SOURCE_FILES is enabled.

FILTER_SOURCE_PATTERNS =

#---------------------------------------------------------------------------
# configuration options related to source browsing
#---------------------------------------------------------------------------

# If the SOURCE_BROWSER tag is set to YES then a list of source files will
# be generated. Documented entities will be cross-referenced with these sources.
# Note: To get rid of all source code in the generated output, make sure also
# VERBATIM_HEADERS is set to NO.

SOURCE_BROWSER         = NO

# Setting the INLINE_SOURCES tag to YES will include the body
# of functions and classes directly in the documentation.

INLINE_SOURCES         = NO

# Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct
# doxygen to hide any special comment blocks from generated source code
# fragments. Normal C, C++ and Fortran comments will always remain visible.

STRIP_CODE_COMMENTS    = YES

# If the REFERENCED_BY_RELATION tag is set to YES
# then for each documented function all documented
# functions referencing it will be listed.

REFERENCED_BY_RELATION = YES

# If the REFERENCES_RELATION tag is set to YES
# then for each documented function all documented entities
# called/used by that function will be listed.

REFERENCES_RELATION    = YES

# If the REFERENCES_LINK_SOURCE tag is set to YES (the default)
# and SOURCE_BROWSER tag is set to YES, then the hyperlinks from
# functions in REFERENCES_RELATION and REFERENCED_BY_RELATION lists will
# link to the source code.
# Otherwise they will link to the documentation.

REFERENCES_LINK_SOURCE = YES

# If the USE_HTAGS tag is set to YES then the references to source code
# will point to the HTML generated by the htags(1) tool instead of doxygen
# built-in source browser. The htags tool is part of GNU's global source
# tagging system (see http://www.gnu.org/software/global/global.html). You
# will need version 4.8.6 or higher.

USE_HTAGS              = NO

# If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen
# will generate a verbatim copy of the header file for each class for
# which an include is specified. Set to NO to disable this.

VERBATIM_HEADERS       = YES

#---------------------------------------------------------------------------
# configuration options related to the alphabetical class index
#---------------------------------------------------------------------------

# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index
# of all compounds will be generated. Enable this if the project
# contains a lot of classes, structs, unions or interfaces.

ALPHABETICAL_INDEX     = NO

# If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then
# the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns
# in which this list will be split (can be a number in the range [1..20])

COLS_IN_ALPHA_INDEX    = 5

# In case all classes in a project start with a common prefix, all
# classes will be put under the same header in the alphabetical index.
# The IGNORE_PREFIX tag can be used to specify one or more prefixes that
# should be ignored while generating the index headers.

IGNORE_PREFIX          =

#---------------------------------------------------------------------------
# configuration options related to the HTML output
#---------------------------------------------------------------------------

# If the GENERATE_HTML tag is set to YES (the default) Doxygen will
# generate HTML output.

GENERATE_HTML          = YES

# The HTML_OUTPUT tag is used to specify where the HTML docs will be put.
# If a relative path is entered the value of OUTPUT_DIRECTORY will be
# put in front of it. If left blank `html' will be used as the default path.

HTML_OUTPUT            = html/refman/ssx

# The HTML_FILE_EXTENSION tag can be used to specify the file extension for
# each generated HTML page (for example: .htm,.php,.asp). If it is left blank
# doxygen will generate files with .html extension.

HTML_FILE_EXTENSION    =

# The HTML_HEADER tag can be used to specify a personal HTML header for
# each generated HTML page. If it is left blank doxygen will generate a
# standard header. Note that when using a custom header you are responsible
#  for the proper inclusion of any scripts and style sheets that doxygen
# needs, which is dependent on the configuration options used.
# It is advised to generate a default header using "doxygen -w html
# header.html footer.html stylesheet.css YourConfigFile" and then modify
# that header. Note that the header is subject to change so you typically
# have to redo this when upgrading to a newer version of doxygen or when
# changing the value of configuration settings such as GENERATE_TREEVIEW!

HTML_HEADER            = ../doc/html/refman/_header.html

# The HTML_FOOTER tag can be used to specify a personal HTML footer for
# each generated HTML page. If it is left blank doxygen will generate a
# standard footer.

HTML_FOOTER            =

# The HTML_STYLESHEET tag can be used to specify a user-defined cascading
# style sheet that is used by each HTML page. It can be used to
# fine-tune the look of the HTML output. If left blank doxygen will
# generate a default style sheet. Note that it is recommended to use
# HTML_EXTRA_STYLESHEET instead of this one, as it is more robust and this
# tag will in the future become obsolete.

HTML_STYLESHEET        =

# The HTML_EXTRA_STYLESHEET tag can be used to specify an additional
# user-defined cascading style sheet that is included after the standard
# style sheets created by doxygen. Using this option one can overrule
# certain style aspects. This is preferred over using HTML_STYLESHEET
# since it does not replace the standard style sheet and is therefor more
# robust against future updates. Doxygen will copy the style sheet file to
# the output directory.

HTML_EXTRA_STYLESHEET  =

# The HTML_EXTRA_FILES tag can be used to specify one or more extra images or
# other source files which should be copied to the HTML output directory. Note
# that these files will be copied to the base HTML output directory. Use the
# $relpath$ marker in the HTML_HEADER and/or HTML_FOOTER files to load these
# files. In the HTML_STYLESHEET file, use the file name only. Also note that
# the files will be copied as-is; there are no commands or markers available.

HTML_EXTRA_FILES       =

# The HTML_COLORSTYLE_HUE tag controls the color of the HTML output.
# Doxygen will adjust the colors in the style sheet and background images
# according to this color. Hue is specified as an angle on a colorwheel,
# see http://en.wikipedia.org/wiki/Hue for more information.
# For instance the value 0 represents red, 60 is yellow, 120 is green,
# 180 is cyan, 240 is blue, 300 purple, and 360 is red again.
# The allowed range is 0 to 359.

HTML_COLORSTYLE_HUE    = 220

# The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of
# the colors in the HTML output. For a value of 0 the output will use
# grayscales only. A value of 255 will produce the most vivid colors.

HTML_COLORSTYLE_SAT    = 100

# The HTML_COLORSTYLE_GAMMA tag controls the gamma correction applied to
# the luminance component of the colors in the HTML output. Values below
# 100 gradually make the output lighter, whereas values above 100 make
# the output darker. The value divided by 100 is the actual gamma applied,
# so 80 represents a gamma of 0.8, The value 220 represents a gamma of 2.2,
# and 100 does not change the gamma.

HTML_COLORSTYLE_GAMMA  = 80

# If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML
# page will contain the date and time when the page was generated. Setting
# this to NO can help when comparing the output of multiple runs.

HTML_TIMESTAMP         = YES

# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML
# documentation will contain sections that can be hidden and shown after the
# page has loaded.

HTML_DYNAMIC_SECTIONS  = NO

# With HTML_INDEX_NUM_ENTRIES one can control the preferred number of
# entries shown in the various tree structured indices initially; the user
# can expand and collapse entries dynamically later on. Doxygen will expand
# the tree to such a level that at most the specified number of entries are
# visible (unless a fully collapsed tree already exceeds this amount).
# So setting the number of entries 1 will produce a full collapsed tree by
# default. 0 is a special value representing an infinite number of entries
# and will result in a full expanded tree by default.

HTML_INDEX_NUM_ENTRIES = 100

# If the GENERATE_DOCSET tag is set to YES, additional index files
# will be generated that can be used as input for Apple's Xcode 3
# integrated development environment, introduced with OSX 10.5 (Leopard).
# To create a documentation set, doxygen will generate a Makefile in the
# HTML output directory. Running make will produce the docset in that
# directory and running "make install" will install the docset in
# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find
# it at startup.
# See http://developer.apple.com/tools/creatingdocsetswithdoxygen.html
# for more information.

GENERATE_DOCSET        = NO

# When GENERATE_DOCSET tag is set to YES, this tag determines the name of the
# feed. A documentation feed provides an umbrella under which multiple
# documentation sets from a single provider (such as a company or product suite)
# can be grouped.

DOCSET_FEEDNAME        = "Doxygen generated docs"

# When GENERATE_DOCSET tag is set to YES, this tag specifies a string that
# should uniquely identify the documentation set bundle. This should be a
# reverse domain-name style string, e.g. com.mycompany.MyDocSet. Doxygen
# will append .docset to the name.

DOCSET_BUNDLE_ID       = org.doxygen.Project

# When GENERATE_PUBLISHER_ID tag specifies a string that should uniquely
# identify the documentation publisher. This should be a reverse domain-name
# style string, e.g. com.mycompany.MyDocSet.documentation.

DOCSET_PUBLISHER_ID    = org.doxygen.Publisher

# The GENERATE_PUBLISHER_NAME tag identifies the documentation publisher.

DOCSET_PUBLISHER_NAME  = Publisher

# If the GENERATE_HTMLHELP tag is set to YES, additional index files
# will be generated that can be used as input for tools like the
# Microsoft HTML help workshop to generate a compiled HTML help file (.chm)
# of the generated HTML documentation.

GENERATE_HTMLHELP      = NO

# If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can
# be used to specify the file name of the resulting .chm file. You
# can add a path in front of the file if the result should not be
# written to the html output directory.

CHM_FILE               =

# If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can
# be used to specify the location (absolute path including file name) of
# the HTML help compiler (hhc.exe). If non-empty doxygen will try to run
# the HTML help compiler on the generated index.hhp.

HHC_LOCATION           =

# If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag
# controls if a separate .chi index file is generated (YES) or that
# it should be included in the master .chm file (NO).

GENERATE_CHI           = NO

# If the GENERATE_HTMLHELP tag is set to YES, the CHM_INDEX_ENCODING
# is used to encode HtmlHelp index (hhk), content (hhc) and project file
# content.

CHM_INDEX_ENCODING     =

# If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag
# controls whether a binary table of contents is generated (YES) or a
# normal table of contents (NO) in the .chm file.

BINARY_TOC             = NO

# The TOC_EXPAND flag can be set to YES to add extra items for group members
# to the contents of the HTML help documentation and to the tree view.

TOC_EXPAND             = NO

# If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and
# QHP_VIRTUAL_FOLDER are set, an additional index file will be generated
# that can be used as input for Qt's qhelpgenerator to generate a
# Qt Compressed Help (.qch) of the generated HTML documentation.

GENERATE_QHP           = NO

# If the QHG_LOCATION tag is specified, the QCH_FILE tag can
# be used to specify the file name of the resulting .qch file.
# The path specified is relative to the HTML output folder.

QCH_FILE               =

# The QHP_NAMESPACE tag specifies the namespace to use when generating
# Qt Help Project output. For more information please see
# http://doc.trolltech.com/qthelpproject.html#namespace

QHP_NAMESPACE          = org.doxygen.Project

# The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating
# Qt Help Project output. For more information please see
# http://doc.trolltech.com/qthelpproject.html#virtual-folders

QHP_VIRTUAL_FOLDER     = doc

# If QHP_CUST_FILTER_NAME is set, it specifies the name of a custom filter to
# add. For more information please see
# http://doc.trolltech.com/qthelpproject.html#custom-filters

QHP_CUST_FILTER_NAME   =

# The QHP_CUST_FILT_ATTRS tag specifies the list of the attributes of the
# custom filter to add. For more information please see
# <a href="http://doc.trolltech.com/qthelpproject.html#custom-filters">
# Qt Help Project / Custom Filters</a>.

QHP_CUST_FILTER_ATTRS  =

# The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this
# project's
# filter section matches.
# <a href="http://doc.trolltech.com/qthelpproject.html#filter-attributes">
# Qt Help Project / Filter Attributes</a>.

QHP_SECT_FILTER_ATTRS  =

# If the GENERATE_QHP tag is set to YES, the QHG_LOCATION tag can
# be used to specify the location of Qt's qhelpgenerator.
# If non-empty doxygen will try to run qhelpgenerator on the generated
# .qhp file.

QHG_LOCATION           =

# If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files
#  will be generated, which together with the HTML files, form an Eclipse help
# plugin. To install this plugin and make it available under the help contents
# menu in Eclipse, the contents of the directory containing the HTML and XML
# files needs to be copied into the plugins directory of eclipse. The name of
# the directory within the plugins directory should be the same as
# the ECLIPSE_DOC_ID value. After copying Eclipse needs to be restarted before
# the help appears.

GENERATE_ECLIPSEHELP   = NO

# A unique identifier for the eclipse help plugin. When installing the plugin
# the directory name containing the HTML and XML files should also have
# this name.

ECLIPSE_DOC_ID         = org.doxygen.Project

# The DISABLE_INDEX tag can be used to turn on/off the condensed index (tabs)
# at top of each HTML page. The value NO (the default) enables the index and
# the value YES disables it. Since the tabs have the same information as the
# navigation tree you can set this option to NO if you already set
# GENERATE_TREEVIEW to YES.

DISABLE_INDEX          = NO

# The GENERATE_TREEVIEW tag is used to specify whether a tree-like index
# structure should be generated to display hierarchical information.
# If the tag value is set to YES, a side panel will be generated
# containing a tree-like index structure (just like the one that
# is generated for HTML Help). For this to work a browser that supports
# JavaScript, DHTML, CSS and frames is required (i.e. any modern browser).
# Windows users are probably better off using the HTML help feature.
# Since the tree basically has the same information as the tab index you
# could consider to set DISABLE_INDEX to NO when enabling this option.

GENERATE_TREEVIEW      = NO

# The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values
# (range [0,1..20]) that doxygen will group on one line in the generated HTML
# documentation. Note that a value of 0 will completely suppress the enum
# values from appearing in the overview section.

ENUM_VALUES_PER_LINE   = 4

# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be
# used to set the initial width (in pixels) of the frame in which the tree
# is shown.

TREEVIEW_WIDTH         = 250

# When the EXT_LINKS_IN_WINDOW option is set to YES doxygen will open
# links to external symbols imported via tag files in a separate window.

EXT_LINKS_IN_WINDOW    = NO

# Use this tag to change the font size of Latex formulas included
# as images in the HTML documentation. The default is 10. Note that
# when you change the font size after a successful doxygen run you need
# to manually remove any form_*.png images from the HTML output directory
# to force them to be regenerated.

FORMULA_FONTSIZE       = 10

# Use the FORMULA_TRANPARENT tag to determine whether or not the images
# generated for formulas are transparent PNGs. Transparent PNGs are
# not supported properly for IE 6.0, but are supported on all modern browsers.
# Note that when changing this option you need to delete any form_*.png files
# in the HTML output before the changes have effect.

FORMULA_TRANSPARENT    = YES

# Enable the USE_MATHJAX option to render LaTeX formulas using MathJax
# (see http://www.mathjax.org) which uses client side Javascript for the
# rendering instead of using prerendered bitmaps. Use this if you do not
# have LaTeX installed or if you want to formulas look prettier in the HTML
# output. When enabled you may also need to install MathJax separately and
# configure the path to it using the MATHJAX_RELPATH option.

USE_MATHJAX            = NO

# When MathJax is enabled you need to specify the location relative to the
# HTML output directory using the MATHJAX_RELPATH option. The destination
# directory should contain the MathJax.js script. For instance, if the mathjax
# directory is located at the same level as the HTML output directory, then
# MATHJAX_RELPATH should be ../mathjax. The default value points to
# the MathJax Content Delivery Network so you can quickly see the result without
# installing MathJax.
# However, it is strongly recommended to install a local
# copy of MathJax from http://www.mathjax.org before deployment.

MATHJAX_RELPATH        = http://cdn.mathjax.org/mathjax/latest

# The MATHJAX_EXTENSIONS tag can be used to specify one or MathJax extension
# names that should be enabled during MathJax rendering.

MATHJAX_EXTENSIONS     =

# When the SEARCHENGINE tag is enabled doxygen will generate a search box
# for the HTML output. The underlying search engine uses javascript
# and DHTML and should work on any modern browser. Note that when using
# HTML help (GENERATE_HTMLHELP), Qt help (GENERATE_QHP), or docsets
# (GENERATE_DOCSET) there is already a search function so this one should
# typically be disabled. For large projects the javascript based search engine
# can be slow, then enabling SERVER_BASED_SEARCH may provide a better solution.

SEARCHENGINE           = NO

# When the SERVER_BASED_SEARCH tag is enabled the search engine will be
# implemented using a PHP enabled web server instead of at the web client
# using Javascript. Doxygen will generate the search PHP script and index
# file to put on the web server. The advantage of the server
# based approach is that it scales better to large projects and allows
# full text search. The disadvantages are that it is more difficult to setup
# and does not have live searching capabilities.

SERVER_BASED_SEARCH    = NO

#---------------------------------------------------------------------------
# configuration options related to the LaTeX output
#---------------------------------------------------------------------------

# If the GENERATE_LATEX tag is set to YES (the default) Doxygen will
# generate Latex output.

GENERATE_LATEX         = NO

# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put.
# If a relative path is entered the value of OUTPUT_DIRECTORY will be
# put in front of it. If left blank `latex' will be used as the default path.

LATEX_OUTPUT           = latex

# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be
# invoked. If left blank `latex' will be used as the default command name.
# Note that when enabling USE_PDFLATEX this option is only used for
# generating bitmaps for formulas in the HTML output, but not in the
# Makefile that is written to the output directory.

LATEX_CMD_NAME         = latex

# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to
# generate index for LaTeX. If left blank `makeindex' will be used as the
# default command name.

MAKEINDEX_CMD_NAME     = makeindex

# If the COMPACT_LATEX tag is set to YES Doxygen generates more compact
# LaTeX documents. This may be useful for small projects and may help to
# save some trees in general.

COMPACT_LATEX          = NO

# The PAPER_TYPE tag can be used to set the paper type that is used
# by the printer. Possible values are: a4, letter, legal and
# executive. If left blank a4wide will be used.

PAPER_TYPE             = letter

# The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX
# packages that should be included in the LaTeX output.

EXTRA_PACKAGES         =

# The LATEX_HEADER tag can be used to specify a personal LaTeX header for
# the generated latex document. The header should contain everything until
# the first chapter. If it is left blank doxygen will generate a
# standard header. Notice: only use this tag if you know what you are doing!

LATEX_HEADER           =

# The LATEX_FOOTER tag can be used to specify a personal LaTeX footer for
# the generated latex document. The footer should contain everything after
# the last chapter. If it is left blank doxygen will generate a
# standard footer. Notice: only use this tag if you know what you are doing!

LATEX_FOOTER           =

# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated
# is prepared for conversion to pdf (using ps2pdf). The pdf file will
# contain links (just like the HTML output) instead of page references
# This makes the output suitable for online browsing using a pdf viewer.

PDF_HYPERLINKS         = NO

# If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of
# plain latex in the generated Makefile. Set this option to YES to get a
# higher quality PDF documentation.

USE_PDFLATEX           = YES

# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode.
# command to the generated LaTeX files. This will instruct LaTeX to keep
# running if errors occur, instead of asking the user for help.
# This option is also used when generating formulas in HTML.

LATEX_BATCHMODE        = NO

# If LATEX_HIDE_INDICES is set to YES then doxygen will not
# include the index chapters (such as File Index, Compound Index, etc.)
# in the output.

LATEX_HIDE_INDICES     = NO

# If LATEX_SOURCE_CODE is set to YES then doxygen will include
# source code with syntax highlighting in the LaTeX output.
# Note that which sources are shown also depends on other settings
# such as SOURCE_BROWSER.

LATEX_SOURCE_CODE      = NO

# The LATEX_BIB_STYLE tag can be used to specify the style to use for the
# bibliography, e.g. plainnat, or ieeetr. The default style is "plain". See
# http://en.wikipedia.org/wiki/BibTeX for more info.

LATEX_BIB_STYLE        = plain

#---------------------------------------------------------------------------
# configuration options related to the RTF output
#---------------------------------------------------------------------------

# If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output
# The RTF output is optimized for Word 97 and may not look very pretty with
# other RTF readers or editors.

GENERATE_RTF           = NO

# The RTF_OUTPUT tag is used to specify where the RTF docs will be put.
# If a relative path is entered the value of OUTPUT_DIRECTORY will be
# put in front of it. If left blank `rtf' will be used as the default path.

RTF_OUTPUT             = rtf

# If the COMPACT_RTF tag is set to YES Doxygen generates more compact
# RTF documents. This may be useful for small projects and may help to
# save some trees in general.

COMPACT_RTF            = NO

# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated
# will contain hyperlink fields. The RTF file will
# contain links (just like the HTML output) instead of page references.
# This makes the output suitable for online browsing using WORD or other
# programs which support those fields.
# Note: wordpad (write) and others do not support links.

RTF_HYPERLINKS         = NO

# Load style sheet definitions from file. Syntax is similar to doxygen's
# config file, i.e. a series of assignments. You only have to provide
# replacements, missing definitions are set to their default value.

RTF_STYLESHEET_FILE    =

# Set optional variables used in the generation of an rtf document.
# Syntax is similar to doxygen's config file.

RTF_EXTENSIONS_FILE    =

#---------------------------------------------------------------------------
# configuration options related to the man page output
#---------------------------------------------------------------------------

# If the GENERATE_MAN tag is set to YES (the default) Doxygen will
# generate man pages

GENERATE_MAN           = NO

# The MAN_OUTPUT tag is used to specify where the man pages will be put.
# If a relative path is entered the value of OUTPUT_DIRECTORY will be
# put in front of it. If left blank `man' will be used as the default path.

MAN_OUTPUT             = man

# The MAN_EXTENSION tag determines the extension that is added to
# the generated man pages (default is the subroutine's section .3)

MAN_EXTENSION          = .3

# If the MAN_LINKS tag is set to YES and Doxygen generates man output,
# then it will generate one additional man file for each entity
# documented in the real man page(s). These additional files
# only source the real man page, but without them the man command
# would be unable to find the correct page. The default is NO.

MAN_LINKS              = NO

#---------------------------------------------------------------------------
# configuration options related to the XML output
#---------------------------------------------------------------------------

# If the GENERATE_XML tag is set to YES Doxygen will
# generate an XML file that captures the structure of
# the code including all documentation.

GENERATE_XML           = NO

# The XML_OUTPUT tag is used to specify where the XML pages will be put.
# If a relative path is entered the value of OUTPUT_DIRECTORY will be
# put in front of it. If left blank `xml' will be used as the default path.

XML_OUTPUT             = xml

# The XML_SCHEMA tag can be used to specify an XML schema,
# which can be used by a validating XML parser to check the
# syntax of the XML files.

XML_SCHEMA             =

# The XML_DTD tag can be used to specify an XML DTD,
# which can be used by a validating XML parser to check the
# syntax of the XML files.

XML_DTD                =

# If the XML_PROGRAMLISTING tag is set to YES Doxygen will
# dump the program listings (including syntax highlighting
# and cross-referencing information) to the XML output. Note that
# enabling this will significantly increase the size of the XML output.

XML_PROGRAMLISTING     = YES

#---------------------------------------------------------------------------
# configuration options for the AutoGen Definitions output
#---------------------------------------------------------------------------

# If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will
# generate an AutoGen Definitions (see autogen.sf.net) file
# that captures the structure of the code including all
# documentation. Note that this feature is still experimental
# and incomplete at the moment.

GENERATE_AUTOGEN_DEF   = NO

#---------------------------------------------------------------------------
# configuration options related to the Perl module output
#---------------------------------------------------------------------------

# If the GENERATE_PERLMOD tag is set to YES Doxygen will
# generate a Perl module file that captures the structure of
# the code including all documentation. Note that this
# feature is still experimental and incomplete at the
# moment.

GENERATE_PERLMOD       = NO

# If the PERLMOD_LATEX tag is set to YES Doxygen will generate
# the necessary Makefile rules, Perl scripts and LaTeX code to be able
# to generate PDF and DVI output from the Perl module output.

PERLMOD_LATEX          = NO

# If the PERLMOD_PRETTY tag is set to YES the Perl module output will be
# nicely formatted so it can be parsed by a human reader.
# This is useful
# if you want to understand what is going on.
# On the other hand, if this
# tag is set to NO the size of the Perl module output will be much smaller
# and Perl will parse it just the same.

PERLMOD_PRETTY         = YES

# The names of the make variables in the generated doxyrules.make file
# are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX.
# This is useful so different doxyrules.make files included by the same
# Makefile don't overwrite each other's variables.

PERLMOD_MAKEVAR_PREFIX =

#---------------------------------------------------------------------------
# Configuration options related to the preprocessor
#---------------------------------------------------------------------------

# If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will
# evaluate all C-preprocessor directives found in the sources and include
# files.

ENABLE_PREPROCESSING   = YES

# If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro
# names in the source code. If set to NO (the default) only conditional
# compilation will be performed. Macro expansion can be done in a controlled
# way by setting EXPAND_ONLY_PREDEF to YES.

MACRO_EXPANSION        = NO

# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES
# then the macro expansion is limited to the macros specified with the
# PREDEFINED and EXPAND_AS_DEFINED tags.

EXPAND_ONLY_PREDEF     = NO

# If the SEARCH_INCLUDES tag is set to YES (the default) the includes files
# pointed to by INCLUDE_PATH will be searched when a #include is found.

SEARCH_INCLUDES        = YES

# The INCLUDE_PATH tag can be used to specify one or more directories that
# contain include files that are not input files but should be processed by
# the preprocessor.

INCLUDE_PATH           =

# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard
# patterns (like *.h and *.hpp) to filter out the header-files in the
# directories. If left blank, the patterns specified with FILE_PATTERNS will
# be used.

INCLUDE_FILE_PATTERNS  =

# The PREDEFINED tag can be used to specify one or more macro names that
# are defined before the preprocessor is started (similar to the -D option of
# gcc). The argument of the tag is a list of macros of the form: name
# or name=definition (no spaces). If the definition and the = are
# omitted =1 is assumed. To prevent a macro definition from being
# undefined via #undef or recursively expanded use the := operator
# instead of the = operator.

PREDEFINED             = DOXYGEN_IGNORE

# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then
# this tag can be used to specify a list of macro names that should be expanded.
# The macro definition that is found in the sources will be used.
# Use the PREDEFINED tag if you want to use a different macro definition that
# overrules the definition found in the source code.

EXPAND_AS_DEFINED      =

# If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then
# doxygen's preprocessor will remove all references to function-like macros
# that are alone on a line, have an all uppercase name, and do not end with a
# semicolon, because these will confuse the parser if not removed.

SKIP_FUNCTION_MACROS   = YES

#---------------------------------------------------------------------------
# Configuration::additions related to external references
#---------------------------------------------------------------------------

# The TAGFILES option can be used to specify one or more tagfiles. For each
# tag file the location of the external documentation should be added. The
# format of a tag file without this location is as follows:
#
# TAGFILES = file1 file2 ...
# Adding location for the tag files is done as follows:
#
# TAGFILES = file1=loc1 "file2 = loc2" ...
# where "loc1" and "loc2" can be relative or absolute paths
# or URLs. Note that each tag file must have a unique name (where the name does
# NOT include the path). If a tag file is not located in the directory in which
# doxygen is run, you must also specify the path to the tagfile here.

TAGFILES               =

# When a file name is specified after GENERATE_TAGFILE, doxygen will create
# a tag file that is based on the input files it reads.

GENERATE_TAGFILE       =

# If the ALLEXTERNALS tag is set to YES all external classes will be listed
# in the class index. If set to NO only the inherited external classes
# will be listed.

ALLEXTERNALS           = NO

# If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed
# in the modules index. If set to NO, only the current project's groups will
# be listed.

EXTERNAL_GROUPS        = YES

# The PERL_PATH should be the absolute path and name of the perl script
# interpreter (i.e. the result of `which perl').

PERL_PATH              = /usr/bin/perl

#---------------------------------------------------------------------------
# Configuration options related to the dot tool
#---------------------------------------------------------------------------

# If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will
# generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base
# or super classes. Setting the tag to NO turns the diagrams off. Note that
# this option also works with HAVE_DOT disabled, but it is recommended to
# install and use dot, since it yields more powerful graphs.

CLASS_DIAGRAMS         = YES

# You can define message sequence charts within doxygen comments using the \msc
# command. Doxygen will then run the mscgen tool (see
# http://www.mcternan.me.uk/mscgen/) to produce the chart and insert it in the
# documentation. The MSCGEN_PATH tag allows you to specify the directory where
# the mscgen tool resides. If left empty the tool is assumed to be found in the
# default search path.

MSCGEN_PATH            =

# If set to YES, the inheritance and collaboration graphs will hide
# inheritance and usage relations if the target is undocumented
# or is not a class.

HIDE_UNDOC_RELATIONS   = YES

# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is
# available from the path. This tool is part of Graphviz, a graph visualization
# toolkit from AT&T and Lucent Bell Labs. The other options in this section
# have no effect if this option is set to NO (the default)

HAVE_DOT               = YES

# The DOT_NUM_THREADS specifies the number of dot invocations doxygen is
# allowed to run in parallel. When set to 0 (the default) doxygen will
# base this on the number of processors available in the system. You can set it
# explicitly to a value larger than 0 to get control over the balance
# between CPU load and processing speed.

DOT_NUM_THREADS        = 0

# By default doxygen will use the Helvetica font for all dot files that
# doxygen generates. When you want a differently looking font you can specify
# the font name using DOT_FONTNAME. You need to make sure dot is able to find
# the font, which can be done by putting it in a standard location or by setting
# the DOTFONTPATH environment variable or by setting DOT_FONTPATH to the
# directory containing the font.

DOT_FONTNAME           = Helvetica

# The DOT_FONTSIZE tag can be used to set the size of the font of dot graphs.
# The default size is 10pt.

DOT_FONTSIZE           = 10

# By default doxygen will tell dot to use the Helvetica font.
# If you specify a different font using DOT_FONTNAME you can use DOT_FONTPATH to
# set the path where dot can find it.

DOT_FONTPATH           =

# If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen
# will generate a graph for each documented class showing the direct and
# indirect inheritance relations. Setting this tag to YES will force the
# CLASS_DIAGRAMS tag to NO.

CLASS_GRAPH            = YES

# If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen
# will generate a graph for each documented class showing the direct and
# indirect implementation dependencies (inheritance, containment, and
# class references variables) of the class with other documented classes.

COLLABORATION_GRAPH    = YES

# If the GROUP_GRAPHS and HAVE_DOT tags are set to YES then doxygen
# will generate a graph for groups, showing the direct groups dependencies

GROUP_GRAPHS           = YES

# If the UML_LOOK tag is set to YES doxygen will generate inheritance and
# collaboration diagrams in a style similar to the OMG's Unified Modeling
# Language.

UML_LOOK               = NO

# If the UML_LOOK tag is enabled, the fields and methods are shown inside
# the class node. If there are many fields or methods and many nodes the
# graph may become too big to be useful. The UML_LIMIT_NUM_FIELDS
# threshold limits the number of items for each type to make the size more
# managable. Set this to 0 for no limit. Note that the threshold may be
# exceeded by 50% before the limit is enforced.

UML_LIMIT_NUM_FIELDS   = 10

# If set to YES, the inheritance and collaboration graphs will show the
# relations between templates and their instances.

TEMPLATE_RELATIONS     = YES

# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT
# tags are set to YES then doxygen will generate a graph for each documented
# file showing the direct and indirect include dependencies of the file with
# other documented files.

INCLUDE_GRAPH          = NO

# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and
# HAVE_DOT tags are set to YES then doxygen will generate a graph for each
# documented header file showing the documented files that directly or
# indirectly include this file.

INCLUDED_BY_GRAPH      = NO

# If the CALL_GRAPH and HAVE_DOT options are set to YES then
# doxygen will generate a call dependency graph for every global function
# or class method. Note that enabling this option will significantly increase
# the time of a run. So in most cases it will be better to enable call graphs
# for selected functions only using the \callgraph command.

CALL_GRAPH             = NO

# If the CALLER_GRAPH and HAVE_DOT tags are set to YES then
# doxygen will generate a caller dependency graph for every global function
# or class method. Note that enabling this option will significantly increase
# the time of a run. So in most cases it will be better to enable caller
# graphs for selected functions only using the \callergraph command.

CALLER_GRAPH           = NO

# If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen
# will generate a graphical hierarchy of all classes instead of a textual one.

GRAPHICAL_HIERARCHY    = YES

# If the DIRECTORY_GRAPH and HAVE_DOT tags are set to YES
# then doxygen will show the dependencies a directory has on other directories
# in a graphical way. The dependency relations are determined by the #include
# relations between the files in the directories.

DIRECTORY_GRAPH        = YES

# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images
# generated by dot. Possible values are svg, png, jpg, or gif.
# If left blank png will be used. If you choose svg you need to set
# HTML_FILE_EXTENSION to xhtml in order to make the SVG files
# visible in IE 9+ (other browsers do not have this requirement).

DOT_IMAGE_FORMAT       = png

# If DOT_IMAGE_FORMAT is set to svg, then this option can be set to YES to
# enable generation of interactive SVG images that allow zooming and panning.
# Note that this requires a modern browser other than Internet Explorer.
# Tested and working are Firefox, Chrome, Safari, and Opera. For IE 9+ you
# need to set HTML_FILE_EXTENSION to xhtml in order to make the SVG files
# visible. Older versions of IE do not have SVG support.

INTERACTIVE_SVG        = NO

# The tag DOT_PATH can be used to specify the path where the dot tool can be
# found. If left blank, it is assumed the dot tool can be found in the path.

DOT_PATH               =

# The DOTFILE_DIRS tag can be used to specify one or more directories that
# contain dot files that are included in the documentation (see the
# \dotfile command).

DOTFILE_DIRS           =

# The MSCFILE_DIRS tag can be used to specify one or more directories that
# contain msc files that are included in the documentation (see the
# \mscfile command).

MSCFILE_DIRS           =

# The DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of
# nodes that will be shown in the graph. If the number of nodes in a graph
# becomes larger than this value, doxygen will truncate the graph, which is
# visualized by representing a node as a red box. Note that doxygen if the
# number of direct children of the root node in a graph is already larger than
# DOT_GRAPH_MAX_NODES then the graph will not be shown at all. Also note
# that the size of a graph can be further restricted by MAX_DOT_GRAPH_DEPTH.

DOT_GRAPH_MAX_NODES    = 50

# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the
# graphs generated by dot. A depth value of 3 means that only nodes reachable
# from the root by following a path via at most 3 edges will be shown. Nodes
# that lay further from the root node will be omitted. Note that setting this
# option to 1 or 2 may greatly reduce the computation time needed for large
# code bases. Also note that the size of a graph can be further restricted by
# DOT_GRAPH_MAX_NODES. Using a depth of 0 means no depth restriction.

MAX_DOT_GRAPH_DEPTH    = 0

# Set the DOT_TRANSPARENT tag to YES to generate images with a transparent
# background. This is disabled by default, because dot on Windows does not
# seem to support this out of the box. Warning: Depending on the platform used,
# enabling this option may lead to badly anti-aliased labels on the edges of
# a graph (i.e. they become hard to read).

DOT_TRANSPARENT        = NO

# Set the DOT_MULTI_TARGETS tag to YES allow dot to generate multiple output
# files in one run (i.e. multiple -o and -T options on the command line). This
# makes dot run faster, but since only newer versions of dot (>1.8.10)
# support this, this feature is disabled by default.

DOT_MULTI_TARGETS      = NO

# If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will
# generate a legend page explaining the meaning of the various boxes and
# arrows in the dot generated graphs.

GENERATE_LEGEND        = YES

# If the DOT_CLEANUP tag is set to YES (the default) Doxygen will
# remove the intermediate dot files that are used to generate
# the various graphs.

DOT_CLEANUP            = YES

Changes to lib/utility.h.

1
2
3

4
5
6
7
8
9

10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
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












/// \file utility.h
/// \brief Declares utility functions used within MySQL++
///

/// None of this is meant to be used outside the library itself.  None
/// of this is considered part of the library interface.  It is subject
/// to change at any time, with no notice.

/***********************************************************************
 Copyright (c) 2009 by Warren Young.  Others may also hold copyrights

 on code in this file.  See the CREDITS.txt file in the top directory
 of the distribution for details.

 This file is part of MySQL++.

 MySQL++ is free software; you can redistribute it and/or modify it
 under the terms of the GNU Lesser General Public License as published
 by the Free Software Foundation; either version 2.1 of the License, or
 (at your option) any later version.

 MySQL++ is distributed in the hope that it will be useful, but WITHOUT
 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
 License for more details.

 You should have received a copy of the GNU Lesser General Public
 License along with MySQL++; if not, write to the Free Software
 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
 USA
***********************************************************************/

#if !defined(MYSQLPP_UTILITY_H)
#define MYSQLPP_UTILITY_H

#include "common.h"

#include <cctype>
#include <cstring>

#include <string>


namespace mysqlpp {
	/// \brief Namespace for holding things used only within MySQL++




	namespace internal {








		/// \brief Lowercase a C++ string in place







		void MYSQLPP_EXPORT str_to_lwr(std::string& s);


		/// \brief Copy a C string into a C++ string, lowercasing
		/// it along the way

		void MYSQLPP_EXPORT str_to_lwr(std::string& ls, const char* mcs);


	} // end namespace mysqlpp::internal



} // end namespace mysqlpp






#endif // !defined(MYSQLPP_UTILITY_H)












|
|
<
>
|
|
|

<
|
>
|
|



















<
|

|

<

>
|
>

|
|
>
>
>
>
|
>
>
>
>
>
>
>
>
|
>
>
>
>
>
>
>
|
>
|
|
<
>
|
>
>
|
>
>
>
|
>
>
>
>
>
|
<
>
>
>
>
>
>
>
>
>
>
>
>
1
2

3
4
5
6
7

8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
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
56
57
58
59
60
61
62
63
64
65
66

67
68
69
70
71
72
73
74
75
76
77
78
79
80
81

82
83
84
85
86
87
88
89
90
91
92
93
/***********************************************************************
 ssx/genv2.cpp - Walks the SSQLS v2 parse result, writing back out

 	the equivalent SSQLS v2 DSL code.  This is useful for testing that
	our parser has correctly understood a given piece of code.  It is
	also something like the preprocessor mode of a C++ compiler,
	emitting a digested version of its input.


 Copyright (c) 2009 by Warren Young and (c) 2009-2010 by Educational
 Technology Resources, Inc.  Others may also hold copyrights on code
 in this file.  See the CREDITS.txt file in the top directory of the
 distribution for details.

 This file is part of MySQL++.

 MySQL++ is free software; you can redistribute it and/or modify it
 under the terms of the GNU Lesser General Public License as published
 by the Free Software Foundation; either version 2.1 of the License, or
 (at your option) any later version.

 MySQL++ is distributed in the hope that it will be useful, but WITHOUT
 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
 License for more details.

 You should have received a copy of the GNU Lesser General Public
 License along with MySQL++; if not, write to the Free Software
 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
 USA
***********************************************************************/


#include "genv2.h"

#include "parsev2.h"


#include <cstring>
#include <iostream>
#include <fstream>
#include <typeinfo>

using namespace std;

//// generate_ssqls2 ///////////////////////////////////////////////////
// 2 versions: second checks its arguments and opens the named file,
// calling the second to actually generate the SSQLS v2 output from
// the parse result only if we were given sane parameters.

static bool
generate_ssqls2(ostream& os, const ParseV2* pparse)
{
	ParseV2::LineListIt it;
	for (it = pparse->begin(); it != pparse->end(); ++it) {
		if (dynamic_cast<ParseV2::Field*>(*it)) {
			// 'field' directives must be indented under the preceding
			// 'table'.  We don't want to hard-code this in
			// ParseV2::Field::print() in case we later start calling
			// those routines for other reasons, such as to construct
			// error messages.  It's really a special case of -o, not
			// really something that print() routine should know.
			os << '\t';
		}
		os << **it << endl;
	}

	return true;
}


bool
generate_ssqls2(const char* file_name, const ParseV2* pparse)
{
	if (pparse) {
		if (strcmp(file_name, "-") == 0) {
			return generate_ssqls2(cout, pparse);
		}
		else {
			ofstream ofs(file_name);
			if (ofs) {
				cout << "TRACE: Generating SSQLS v2 file " << file_name <<
						" from " << (pparse->end() - pparse->begin()) <<
						" line parse result." << endl;
				return generate_ssqls2(ofs, pparse);
			}

			else {
				cerr << "Failed to open " << file_name << \
						" for writing for -o!" << endl;
				return false;
			}
		}
	}
	else {
		cerr << "No parse result given to -o handler!" << endl;
		return false;
	}
}

Changes to lib/vallist.cpp.

1

2
3
4
5
6
7


8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
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
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83

84
85
86
87
88
89
90
91
92
93
94
95
96




97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
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
144
/***********************************************************************

 vallist.cpp - Implements utility functions for building value lists.
	This is internal functionality used within the library.

 Copyright (c) 1998 by Kevin Atkinson, (c) 1999, 2000 and 2001 by
 MySQL AB, and (c) 2004-2007 by Educational Technology Resources, Inc.
 Others may also hold copyrights on code in this file.  See the CREDITS


 file in the top directory of the distribution for details.

 This file is part of MySQL++.

 MySQL++ is free software; you can redistribute it and/or modify it
 under the terms of the GNU Lesser General Public License as published
 by the Free Software Foundation; either version 2.1 of the License, or
 (at your option) any later version.

 MySQL++ is distributed in the hope that it will be useful, but WITHOUT
 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
 License for more details.

 You should have received a copy of the GNU Lesser General Public
 License along with MySQL++; if not, write to the Free Software
 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
 USA
***********************************************************************/

#include "vallist.h"

#include "result.h"
#include "row.h"

using std::string;

namespace mysqlpp {





void
create_vector(size_t size, std::vector<bool>& v, bool t0, bool t1, bool t2,
		bool t3, bool t4, bool t5, bool t6, bool t7, bool t8, bool t9,
		bool ta, bool tb, bool tc)
{

	v.reserve(size);

	v.push_back(t0);
	if (size == 1) return;

	v.push_back(t1);
	if (size == 2) return;

	v.push_back(t2);
	if (size == 3) return;

	v.push_back(t3);
	if (size == 4) return;

	v.push_back(t4);
	if (size == 5) return;

	v.push_back(t5);
	if (size == 6) return;

	v.push_back(t6);
	if (size == 7) return;

	v.push_back(t7);
	if (size == 8) return;

	v.push_back(t8);
	if (size == 9) return;

	v.push_back(t9);
	if (size == 10) return;

	v.push_back(ta);
	if (size == 11) return;

	v.push_back(tb);
	if (size == 12) return;

	v.push_back(tc);
}



template <class Container>
void create_vector(const Container& c, std::vector<bool>& v,
		std::string s0, std::string s1, std::string s2, std::string s3,
		std::string s4, std::string s5, std::string s6, std::string s7,
		std::string s8, std::string s9, std::string sa, std::string sb,
		std::string sc)
{
	v.insert(v.begin(), c.size(), false);

	v[c.field_num(s0.c_str())] = true;
	if (s1.empty()) return;

	v[c.field_num(s1.c_str())] = true;




	if (s2.empty()) return;

	v[c.field_num(s2.c_str())] = true;
	if (s3.empty()) return;

	v[c.field_num(s3.c_str())] = true;
	if (s4.empty()) return;

	v[c.field_num(s4.c_str())] = true;
	if (s5.empty()) return;

	v[c.field_num(s5.c_str())] = true;
	if (s6.empty()) return;

	v[c.field_num(s6.c_str())] = true;
	if (s7.empty()) return;

	v[c.field_num(s7.c_str())] = true;
	if (s8.empty()) return;

	v[c.field_num(s8.c_str())] = true;
	if (s9.empty()) return;

	v[c.field_num(s9.c_str())] = true;
	if (sa.empty()) return;

	v[c.field_num(sa.c_str())] = true;
	if (sb.empty()) return;

	v[c.field_num(sb.c_str())] = true;
	if (sc.empty()) return;

	v[c.field_num(sc.c_str())] = true;
}



#if !defined(DOXYGEN_IGNORE)
// Instantiate above template.  Not sure why this is necessary.  Hide it
// from Doxygen, because we clearly cannot appease it by documenting it.
template void
create_vector(const Row& c, std::vector<bool>& v, string s0,
		string s1, string s2, string s3, string s4, string s5,
		string s6, string s7, string s8, string s9, string sa,
		string sb, string sc);
#endif

} // end namespace mysqlpp

<
>
|
|
|
<
<
|
>
>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<
<
|
<
|
<
<
|
<
|
|
|
>
>
>
>
|
|
|
|
<
>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<
<
|
|
|
|
|
|
|
|
<
|
|
>
|
|
|
|
|
<
<
<
|
|
<
|
|
>
>
>
>
|
|
|
|
|
|
|
|
|
<
|
<
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<
|
|
>
|
|
|
|
|
|
|
<
<
|
|
|

1
2
3
4


5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24


25

26


27

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
56
57
58
59
60
61
62
63
64
65
66
67
68


69
70
71
72
73
74
75
76

77
78
79
80
81
82
83
84



85
86

87
88
89
90
91
92
93
94
95
96
97
98
99
100
101

102

103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123

124
125
126
127
128
129
130
131
132
133


134
135
136

C Version\s2.2.2
D 2007-04-13T15:30:48.000
F Bakefiles.bkgen e4b228b8a40f0b135b32b78713a94aedde0a568538be3ef752afb15ce7409ec3
F COPYING 9e0b7eacf0a68b311788ad80a5af9eef865014ff9fae62aa67784b5175807e77


F CREDITS 7afd3cb56aaa32221c06366506216140c207df14e5a3f45f62f3b637ac728e90
F ChangeLog ec0d770b2bf46f330555f1498a4580594215bc463b86bdd343a066b8da367363
F HACKERS 9722076023eca18ec9480ac821a9752ccd1e41c4daddb82443a53ff1ca7c2dbe
F INSTALL 999904fea23719945cfbe2ba070e457bc933933a17babaccff9ca3bc598e4b64
F LICENSE 97ebb45ce18ea0be5a31a8aec2228eee997e3ed3df0aa31771ade1999d483a82
F Makefile.mingw 98f9f7f8147ab38b85d4aa93fd3f1d292cb6622803bf53ffa1d52a4847f4b106
F Makefile.simple 27c15f0fd6bd6721821e577cd4f1d228fc2fbe8ad8212ecff38946ad3aa46eec
F README 80f7d28bccebef8aef56043c2c9f5a13d7178c06322a34140c77459155f57f76
F README.cygwin 863292e0e7be19443c6c5460e9348562aa1bffc7b97751de2485328b257eb662
F README.examples b9f1c38f15c2eb12d088bbc4eebba2630d1021e765d44547a9aa397f2f7f137c
F README.mingw 5ad0f040f4525a522867b1c9d7f2c86c2333240903fdda26e4a770ea3d04c1c4
F README.unix 15566d1ee0c4bd9a9093463d0e1a37a19d5d8c16b4dee867c34cc1fdadcb6c62
F README.vc d54e33933e55c6bde77a3655f9a5f8099998475a515672584e19e3c1768d7aaf
F Wishlist db6c2012b3d9b0576ff4683efe1278251bd7166bf338a6dd7af9c60f443469bb
F bootstrap ff9a1176a9bb958b5ee1e69c93d92c042678ce204fb10a3d1f331e3b38f5ece6 x
F cleanmf 57cdbbd1b6e42ae343509574e7d6bad9764d7c4457c8687b12f802ca3a62b866 x
F config.h.in 37ef775594a696f984cb4e5ec75124405e43a2c04acc70ebd7cf5fa6257a688c
F config/acx_pthread.m4 699c3dd85117c5817bf5882102903c6a9248b304e14dcf60cecc3c35cede6ff6
F config/autoconf_inc.m4 40b29871c42d655b3b088e86ed170f39653b8ec7f8ddf88ad971ab16ab71b8c1
F config/libm.m4 de3dcf0b6e8149f13c9e26dcdeaf25bf5b40fa3993546835b29c0a3be6ee63ea


F config/localtime_r.m4 8ba2bda9bdf152d8f901180b2eec716f75c381c5ed2d98666f4f0cfe29152256

F config/mysql++.m4 07e197cf867eeebd2856a303c9f7c0144e9b3bdc93df52ddf2c9cbda46efc84c


F config/mysql_loc.m4 825474857f043f73f01a635eaeebf81eba7a858c0747f8c55ac788bbe09825ee

F config/mysql_shutdown.m4 e1ceaf00dcb4d36c4119d0f23b38aa9cfbdf2ee82b73fe308a8022f80e4d0cdb
F config/mysql_ssl.m4 82d5c48515915eec8c2c817216a31b1f5a167382b150e547a306e5715905ce57
F config/socket_nsl.m4 6dd364d066feec0abf2b2bcdd377710010c459d3c6fbedad77a20f38997c7de2
F config/stl_slist.m4 614e5c3929b7b506b1f61ce6a4f089a5ef5acc049a0920963a32dd2bd11ad7c1
F configure.ac c5b0c4f19f35e2e530b32d6b97551b5f3f0786e81e042cb5543847a78c4b5e79
F doc/README.devel 598f23f0e963c2aeccff69a5aa3fcaf1cd02462a8df8c63a08c953c85f705d93
F doc/README.manuals 12316b39e05f17d22d378647a574c7f6d1a12bca86ca75c54e761555b9f34763
F doc/ssqls-pretty df7ad3cb7ea092525d53215c88767eb3ef03bd5b84c033398118331bd04f6480 x
F doc/userman/LICENSE 072e94ba2bf3d5ca1013dea060629d6aacb3855ac2fb849180f6c552176e4158
F doc/userman/Makefile 6cc1a92446683707c7bc1f45cbd0646e53fd64f169d1c28b7814de76b1448494
F doc/userman/README 5c5f91f9237cf53610e275a7ded182be0d0408a40bacc3ca6bcfaa4a4073b6fc

F doc/userman/common.xsl 77ce21b7da6c7b1f651703fa8f1ea5170bae37438c9101456a6aff08918c4792
F doc/userman/fo.xsl a6ef7eb5f10f3c63ba0fdc9abbe4aa7f8065632c64937c3cef15ca718e872dac
F doc/userman/html.xsl acaffa4de9387b095cb9bc22508d5bebfeccb5c4c506bb067ca0dc881536b554
F doc/userman/mktxt d7fb06e2c293cb0106ec5ba5508757022740f07e79f96065925735fa11506374 x
F doc/userman/userman.dbx f71130d7974595f640a0151af0ebc8efa56463c7ee4440ef45f57e3b65c83bc0
F examples/cgi_jpeg.cpp c097e9afd2385496adc4efd9e6f24fce4f4a920efe0eea4766a1231ae6b30d04
F examples/custom1.cpp 8d1d872b3ed8a8b71f0c5c110b1fd7d574b842ab4118a3027feb47bcaf486a72
F examples/custom2.cpp dfa240a7cae5e242dfa8cf3eb36f118880e76a634946d26d2a8576125696eb0b
F examples/custom3.cpp 575047351d4a201969d72eeb455935a9e37b447c24bf56b8f0900128637757bf
F examples/custom4.cpp 4767c7ebb7aef204e15acc83f85a43ffbcd85b1a905f274e931346c3b92b6f34
F examples/custom5.cpp c6c89a7560e8e7a3edbd2c6b03c1c0987143f254d3aae4a3f25758909e7824df
F examples/custom6.cpp ad09137e64fb236e6e540af021888c43cc6bf21b27d1d120363d694b8c64ae5a
F examples/dbinfo.cpp 926be9e2b9ed53c72590b740fb57a171c4ebfaf0f09a663aeed6909a6c252a94
F examples/fieldinf1.cpp 03ae45e5cb8054bc3d439b23d1cff842327a240d044e66baa772c901b4c3eae5
F examples/load_jpeg.cpp 9106fbf818cd3030385da478466bf075a28de02579f723ae2059e6968a1e283a
F examples/logo.jpg b551f2a4609684c83c17acc32faa08af659df397aba70fe7e0f12de82c4bc934
F examples/multiquery.cpp 47bbd79eb9c64b5cafda123c6e50317aed653aa5f14400b49b2763fec6d93f97
F examples/resetdb.cpp 146a02902c01e0c49b7cc6c9c0267a6afd97f5e3f780c6a8d920ebea6f38d193
F examples/simple1.cpp 738c6ae3e16dbb4611071fc39f90758cb2aee9ff43f470d34c5e0744f4ba44d7
F examples/simple2.cpp afa75f586f719443051d7776158e863bd99da63206a183362307ace413c9ac10
F examples/simple3.cpp fe83b1b72ddae309514e0a36fe9e89640aafc1361de49233d1377624e49059e9
F examples/stock.h 032b2ee588a50be5abd3a0d169fdbc90999607356d41bc706197670a47687342
F examples/tquery.cpp 2529c6d61dc29236fd1afca95443824fa9a983ae2aad4f5a5d93a3121b5f4a04
F examples/updel.cpp f7094d7f2f584b219990fa7901b6ca16640ad0b953120b1bc2543d2e63e13b95
F examples/usequery.cpp 99faa9071fb3ebf5d5fc9d38b842d0c21b494829335b406a76042c531d597981
F examples/util.cpp 8bb2166a1b693d024e1f2063716e5e5641a7b7e6b505cada8ce87f1ee400a61d
F examples/util.h e75d10d29b8ff2d099abe19ce82b550919788baaea520d373049d59f2afabc09
F examples/xaction.cpp f6613dd32b9ee226ae48b30288f73f8bdb5bf16825589d127f50108721ba2be2
F exrun 4e85e39d284af71d5ae1afabe7a302599515bec0f19ea264d3cdc3e17c8a1e73 x
F exrun.bat 34ad10adecfc4caa80dca5266257c5ddffdaf11b843cbbf2331863099eae538d x


F install.bat 24ccc18301277c307f4df2f88ed3cb9d6e926bd6dbc9e353a910f99952758ed5
F lib/Doxyfile.in a2c217527795396d1d287422c76b976518d95e39f1adc7946daaba9f7389d148
F lib/autoflag.h a59c91082888a869068a2ecaeb15187fd0ead8ea49dcc46c3602ecea6d13e1a5
F lib/coldata.cpp 1a067cdbed44125824d669a3287b6c8e020fd68fff1243a5994e54f0d4d0b52b
F lib/coldata.h beba79b15f7ee3702703289e61c9d0d9420a9cecb21f309dc0c5e4f01255e252
F lib/common.h 0683ee39147700828b2be954d6f5244918ecaa7013a1d3e8d1909ed124ac04e8
F lib/connection.cpp d0ef213f1bae0cdc82d1e2fe9af8986afbc28e39d9f39bd7d247e9784c2be131
F lib/connection.h 5b49012221180e66ace829dbc837d86a1113942f8bbdae59394c5b93ba969f2e

F lib/const_string.h bc3505f6fa9247e7925ca2f68b578f83eb7d2deb00299e3d93ca8981f13f90e4
F lib/convert.h b5186cad54a7f1926417fe0c155c5b53b50322165821dbf47ff06ef2ae27b3a2
F lib/custom-macros.h d660286cc5de19392e6f4a8d8a1580a37892b3b73c66f47d138b8f4321da26d1
F lib/custom.h b0b538fdd2a5d97291f34863c31d31c009b4809058186ff4ddaa9c5c7850463b
F lib/custom.pl 6913224d33e8abfd80159f76d897011658a2869bf8b2f8db261a91c563a5729e x
F lib/datetime.cpp 36ff7d86c0900406627125e2c39e0e835f2cc69932ef3bd2f3327efd1960de2c
F lib/datetime.h 637ace4ed5d9e16f8ffa868dadc5433553569e1a6b30568e8423846a9bb2930e
F lib/exceptions.h 7fb1bc4256f16cd991fd34c85e07946bb2c1f4c7b6e67c33e6dd656a1eba5036



F lib/field_names.cpp 879de31ec45bebf2f37a3b925bb2e5847506e87c12eaad1948956657566bcc37
F lib/field_names.h 169c6c530c83de7e27ba903f5b7d82ec77866926d3e543d97bcfc14e517a7330

F lib/field_types.cpp e539fa4033b5e05c3895c78b3cacf573fdb136e6b7bd0181b7a2de05cd3ce905
F lib/field_types.h cd9e867c989758186988e2a16357ef10fc50b3ba2293ebcd215fbb0833cba872
F lib/fields.cpp 8f381e05012812a95b61b9b71beaebad241eef558e549cc3f905d4db1d11360d
F lib/fields.h f25d8a1287056eb35240a3d58049b48fb5c8421435c5421ee6cf1f117e1aab5b
F lib/lockable.h 708200383865bfbd854862aebbf52c1bb90079285cd743e4093b058aaf62c9f9
F lib/manip.cpp 5700390345896ce5c45be14504cef167a576831af6795f9b7ffdd60bfa4aef71
F lib/manip.h ce9b912ae660285d16b2e385de2e1492af3b83fb29ef557a9b096d11e96f96a2
F lib/myset.cpp 462c808158c304a45340a3bcb04bbfe25ecc36103ad2b88812f2efe7b1cd9f00
F lib/myset.h 0bdf3736fae02c015e9f595aad10fc23f19b3000fbaf860b7fa07fe6c8008086
F lib/mysql++.cpp 4208335c42b3a92cf374da003176a971b25fc95654c8fa12c910ea9a2c281078
F lib/mysql++.h.in 6b1e89664b4be86bb7715f40e6b90ff0e7f87273c5d5bb11359dbf91a63f576f
F lib/noexceptions.h 5980f0b36e551837dce40fbf4bce5c8041e83ac3524f7a71ca2e34b1bd74fb42
F lib/null.h f8c57010f23ad0e57e4cab2941cab9fe07594952d28bc122e51ae48eb189be80
F lib/qparms.cpp e9872b9e50f98956f447e0cebd99d575ab7438329c80b76b776007a32f161eac
F lib/qparms.h d26cee45209890aa8c5cef5adb85d65e65eb2c1cc155745fb3777f0df7fc659b

F lib/query.cpp 7634d00d89441fa48dd9f88660de0f82607957dc6a6ce6f2b31f8985670b0919

F lib/query.h e2e77858efb16d09bf3c25b50b68e114f49e620ddba4c907a9ca9c7241b57bec
F lib/querydef.h 6fe5f89b24cd2999941ce712074725261f308d7e384c411199b8be2daad216c4
F lib/querydef.pl d59c57feaf8d59c8aaf60c380d67b838aa2514eb3cfd2bd108db391a960ff2e4 x
F lib/resiter.h f4495ec17723115d01b0ebe8543146afa29069061300a55aaac270611dd58b69
F lib/result.cpp d1cde96698e2080dabd7fcca03d327f2bf714a388eadf9a9652e4c5d15235542
F lib/result.h 73f4d505c3e4d2f2c4547be4ac927de92742e201dbf79001e5c7d4231d1dafd6
F lib/row.cpp abaf2b03b109307c9a2044cf19ee818b07d1c1c38959fb39b6f002c052909368
F lib/row.h 7c6784900ddba993521486f3e6d132b215bf3ea0a434f9e0d0f837027a7d456f
F lib/sql_string.cpp 3c2ef8136ad697bcc3b84efa3428aa6be4454d3901f412285c212ac63b2599c0
F lib/sql_string.h 2322d1cbb9e9b6341e4aafd82331c700494532aea71c3acbdde01d89c62ca9ba
F lib/sql_types.h bc74c847e59d56b1dffc45c0eb5bf25b4a9f2e31a5bac8dd13891fc4a5d450c5
F lib/stream2string.h 433c7571f769496465a3b6dd76439bd7e9d8ac3ace7e800e4492d32dfdd7c70b
F lib/string_util.cpp 8de61ba66aeb50027643a6e9b410894589eb1ed76d7f7510b6ef6cbb63de28bd
F lib/string_util.h 73b64d9e41ce169061cc5e7322a9c7dab23196800372a6a788442082859e1c5e
F lib/tiny_int.h afff8c429bb607fa04ccde3438285497ac440ef5c08e24044c54fa1f9b09f750
F lib/transaction.cpp bcb495ada3826986a20ae0753953657d7b4c6f6089adc5b2f72741833d2f32a4
F lib/transaction.h 4c6f2e8d98c706f9f9eb7182fa044d2cef2a739c0c624d16f3d3508e00a39009
F lib/type_info.cpp 5a227272037acf7d06f8c8530937dc6f190fce642f38fa248f1be993bfac72e2
F lib/type_info.h 9fdaac36d7e11107171c9e1941430a0e2f1a1f382e436503ea5b5bddbd0d2c53
F lib/vallist.cpp f6297fe092d2769b9838bec83f3840b6befbead47f7ebc21d1eeb06b2bccab93
F lib/vallist.h 50e782e8fc593690727e5bae9659ca7467bad4d1726469b4abdf6c649c1cefe3

F libmysqlclient.def 9e9d8912ff597d08201437748dcb5bf3286d95428bd2b1986d6a39ef70ab507d
F mysql++.bkl 91e3c21049d0b43680545d93dc408c366d3176cf0cd04e8e63564c467914141d
F mysql++.ebuild b6c40546ff62865a0ddeafc3feca6340d9a91c81f3d6a3af84979d5010b18b6e
F mysql++.spec.in f560e85c1a2afc0239f4cb7d92838d210a818c7ad4fa5c96d0c7cf724b9f48a7
F osver 034cabb5f0517c3b0a3bedcf712289fd6b4b205ee9576940a1440dc85060c230 x
F pretty.pl 011358a7e49ceab10b1bcd5e8484edd2b28e3874723ffa95677b79f74ae7e010 l
F rebake 1aea79a8b83041adba94d3f61d33aa788509f93f123a60f68454a6ffdc0d72e6 x
F reconf 860432601e900eeea5ea70e6b73456f0f28b6a7f9920716b80c8a263ff65467a x
P d4ffec1de150b8c45cb73e5345ff381577a64f206f583bf5c180ea493fc09c03
R 5c2b7e7a576162ffcc4d21bb8d1d304b


T +sym-v2.2.2 *
U tangent
Z 9ce9f09a30a2226d2eb12f0263fd23b5

Changes to lib/vallist.h.

1
2

3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
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
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
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
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
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
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
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
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
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
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504



505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
/// \file vallist.h
/// \brief Declares templates for holding lists of values.


/***********************************************************************
 Copyright (c) 1998 by Kevin Atkinson, (c) 1999, 2000 and 2001 by
 MySQL AB, and (c) 2004, 2005 by Educational Technology Resources, Inc.
 Others may also hold copyrights on code in this file.  See the CREDITS
 file in the top directory of the distribution for details.

 This file is part of MySQL++.

 MySQL++ is free software; you can redistribute it and/or modify it
 under the terms of the GNU Lesser General Public License as published
 by the Free Software Foundation; either version 2.1 of the License, or
 (at your option) any later version.

 MySQL++ is distributed in the hope that it will be useful, but WITHOUT
 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
 License for more details.

 You should have received a copy of the GNU Lesser General Public
 License along with MySQL++; if not, write to the Free Software
 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
 USA
***********************************************************************/

#if !defined(MYSQLPP_VALLIST_H)
#define MYSQLPP_VALLIST_H

#include "manip.h"

#include <string>
#include <vector>

namespace mysqlpp {


/// \brief Holds two lists of items, typically used to construct a
/// SQL "equals clause".
///
/// The WHERE clause in a SQL SELECT statment is an example of an
/// equals clause.
///
/// Imagine an object of this type contains the lists (a, b) (c, d),
/// and that the object's delimiter and equals symbols are set to ", "
/// and " = " respectively.  When you insert that object into a C++
/// stream, you would get "a = c, b = d".
///
/// This class is never instantiated by hand.  The equal_list()
/// functions build instances of this structure template to do their
/// work.  MySQL++'s SSQLS mechanism calls those functions when
/// building SQL queries; you can call them yourself to do similar work.
/// The "Harnessing SSQLS Internals" section of the user manual has
/// some examples of this.
///
/// \sa equal_list_b

template <class Seq1, class Seq2, class Manip>
struct equal_list_ba
{
	/// \brief the list of objects on the left-hand side of the
	/// equals sign
	const Seq1* list1;

	/// \brief the list of objects on the right-hand side of the
	/// equals sign
	const Seq2* list2;

	/// \brief delimiter to use between each pair of elements
	const char* delim;

	/// \brief "equal" sign to use between each item in each equal
	/// pair; doesn't have to actually be " = "
	const char* equl;

	/// \brief manipulator to use when inserting the equal_list into
	/// a C++ stream
	Manip manip;

	/// \brief Create object
	///
	/// \param s1 list of objects on left-hand side of equal sign
	/// \param s2 list of objects on right-hand side of equal sign
	/// \param d what delimiter to use between each group in the list
	///		when inserting the list into a C++ stream
	/// \param e the "equals" sign between each pair of items in the
	/// 	equal list; doesn't actually have to be " = "!
	/// \param m manipulator to use when inserting the list into a
	/// 	C++ stream
	equal_list_ba(const Seq1& s1, const Seq2& s2, const char* d,
			const char* e, Manip m) :
	list1(&s1),
	list2(&s2),
	delim(d),
	equl(e),
	manip(m)
	{
	}
};


/// \brief Same as equal_list_ba, plus the option to have some elements
/// of the equals clause suppressed.
///
/// Imagine an object of this type contains the lists (a, b, c)
/// (d, e, f), that the object's 'fields' list is (true, false, true),
/// and that the object's delimiter and equals symbols are set to
/// " AND " and " = " respectively.  When you insert that object into a
/// C++ stream, you would get "a = d AND c = f".
///
/// See equal_list_ba's documentation for more details.

template <class Seq1, class Seq2, class Manip>
struct equal_list_b
{
	/// \brief the list of objects on the left-hand side of the
	/// equals sign
	const Seq1* list1;

	/// \brief the list of objects on the right-hand side of the
	/// equals sign
	const Seq2* list2;

	/// \brief for each true item in the list, the pair in that position
	/// will be inserted into a C++ stream
	const std::vector<bool> fields;

	/// \brief delimiter to use between each pair of elements
	const char* delim;

	/// \brief "equal" sign to use between each item in each equal
	/// pair; doesn't have to actually be " = "
	const char* equl;

	/// \brief manipulator to use when inserting the equal_list into
	/// a C++ stream
	Manip manip;

	/// \brief Create object
	///
	/// \param s1 list of objects on left-hand side of equal sign
	/// \param s2 list of objects on right-hand side of equal sign
	/// \param f for each true item in the list, the pair of items
	///		in that position will be inserted into a C++ stream
	/// \param d what delimiter to use between each group in the list
	///		when inserting the list into a C++ stream
	/// \param e the "equals" sign between each pair of items in the
	/// 	equal list; doesn't actually have to be " = "!
	/// \param m manipulator to use when inserting the list into a
	/// 	C++ stream
	equal_list_b(const Seq1& s1, const Seq2& s2,
			const std::vector<bool>& f, const char* d,
			const char* e, Manip m) :
	list1(&s1),
	list2(&s2),
	fields(f),
	delim(d),
	equl(e),
	manip(m)
	{
	}
};


/// \brief Holds a list of items, typically used to construct a SQL
/// "value list".
///
/// The SQL INSERT statement has a VALUES clause; this class can
/// be used to construct the list of items for that clause.
///
/// Imagine an object of this type contains the list (a, b, c), and
/// that the object's delimiter symbol is set to ", ".  When you
/// insert that object into a C++ stream, you would get "a, b, c".
///
/// This class is never instantiated by hand.  The value_list()
/// functions build instances of this structure template to do their
/// work.  MySQL++'s SSQLS mechanism calls those functions when
/// building SQL queries; you can call them yourself to do similar work.
/// The "Harnessing SSQLS Internals" section of the user manual has
/// some examples of this.
///
/// \sa value_list_b

template <class Seq, class Manip>
struct value_list_ba
{
	/// \brief set of objects in the value list
	const Seq* list;

	/// \brief delimiter to use between each value in the list when
	/// inserting it into a C++ stream
	const char* delim;

	/// \brief manipulator to use when inserting the list into a
	/// C++ stream
	Manip manip;

	/// \brief Create object
	///
	/// \param s set of objects in the value list
	/// \param d what delimiter to use between each value in the list
	///		when inserting the list into a C++ stream
	/// \param m manipulator to use when inserting the list into a
	/// 	C++ stream
	value_list_ba(const Seq& s, const char* d, Manip m) :
	list(&s),
	delim(d),
	manip(m)
	{
	}
};


/// \brief Same as value_list_ba, plus the option to have some elements
/// of the list suppressed.
///
/// Imagine an object of this type contains the list (a, b, c), that
/// the object's 'fields' list is (true, false, true), and that the
/// object's delimiter is set to ":".  When you insert that object
/// into a C++ stream, you would get "a:c".
///
/// See value_list_ba's documentation for more details.

template <class Seq, class Manip>
struct value_list_b
{
	/// \brief set of objects in the value list
	const Seq* list;

	/// \brief delimiter to use between each value in the list when
	/// inserting it into a C++ stream
	const std::vector<bool> fields;

	/// \brief delimiter to use between each value in the list when
	/// inserting it into a C++ stream
	const char* delim;

	/// \brief manipulator to use when inserting the list into a C++
	/// stream
	Manip manip;

	/// \brief Create object
	///
	/// \param s set of objects in the value list
	/// \param f for each true item in the list, the list item
	///		in that position will be inserted into a C++ stream
	/// \param d what delimiter to use between each value in the list
	///		when inserting the list into a C++ stream
	/// \param m manipulator to use when inserting the list into a
	///		C++ stream
	value_list_b(const Seq& s, const std::vector<bool>& f,
			const char* d, Manip m) :
	list(&s),
	fields(f),
	delim(d),
	manip(m)
	{
	}
};


/// \brief Inserts an equal_list_ba into an std::ostream.
///
/// Given two lists (a, b) and (c, d), a delimiter D, and an equals
/// symbol E, this operator will insert "aEcDbEd" into the stream.
///
/// See equal_list_ba's documentation for concrete examples.
///
/// \sa equal_list()

template <class Seq1, class Seq2, class Manip>
std::ostream& operator <<(std::ostream& o,
		const equal_list_ba<Seq1, Seq2, Manip>& el)
{
	typename Seq1::const_iterator i = el.list1->begin();
	typename Seq2::const_iterator j = el.list2->begin();

	while (1) {
		o << *i << el.equl << el.manip << *j;
		if ((++i == el.list1->end()) || (++j == el.list2->end())) {
			break;
		}
		o << el.delim;
	}

	return o;
}


/// \brief Same as operator<< for equal_list_ba, plus the option to
/// suppress insertion of some list items in the stream.
///
/// See equal_list_b's documentation for examples of how this works.

template <class Seq1, class Seq2, class Manip>
std::ostream& operator <<(std::ostream& o,
		const equal_list_b <Seq1, Seq2, Manip>& el)
{
	typename Seq1::const_iterator i = el.list1->begin();
	typename Seq2::const_iterator j = el.list2->begin();

	int k = 0;
	while (1) {
		if (el.fields[k++]) {
			o << *i << el.equl << el.manip << *j;
		}
		if ((++i == el.list1->end()) || (++j == el.list2->end())) {
			break;
		}
		if (el.fields[k]) {
			o << el.delim;
		}
	}

	return o;
}


/// \brief Inserts a value_list_ba into an std::ostream.
///
/// Given a list (a, b) and a delimiter D, this operator will insert
/// "aDb" into the stream.
///
/// See value_list_ba's documentation for concrete examples.
///
/// \sa value_list()

template <class Seq, class Manip>
std::ostream& operator <<(std::ostream& o,
		const value_list_ba<Seq, Manip>& cl)
{
	typename Seq::const_iterator i = cl.list->begin();

	while (1) {
		o << cl.manip << *i;
		if (++i == cl.list->end()) {
			break;
		}
		o << cl.delim;
	}

	return o;
}


/// \brief Same as operator<< for value_list_ba, plus the option to
/// suppress insertion of some list items in the stream.
///
/// See value_list_b's documentation for examples of how this works.

template <class Seq, class Manip>
std::ostream& operator <<(std::ostream& o,
		const value_list_b<Seq, Manip>& cl)
{
	typename Seq::const_iterator i = cl.list->begin();

	int k = 0;
	while (1) {
		if (cl.fields[k++]) {
			o << cl.manip << *i;
		}
		if (++i == cl.list->end()) {
			break;
		}
		if (cl.fields[k]) {
			o << cl.delim;
		}
	}

	return o;
}


/// \brief Create a vector of bool with the given arguments as values.
///
/// This function takes up to 13 bools, with the size parameter
/// controlling the actual number of parameters we pay attention to.
///
/// This function is used within the library to build the vector used
/// in calling the vector form of Row::equal_list(), Row::value_list(),
/// and Row::field_list().  See the "Harnessing SSQLS Internals" section
/// of the user manual to see that feature at work.

void create_vector(size_t size, std::vector<bool>& v, bool t0,
		bool t1 = false, bool t2 = false, bool t3 = false,
		bool t4 = false, bool t5 = false, bool t6 = false,
		bool t7 = false, bool t8 = false, bool t9 = false,
		bool ta = false, bool tb = false, bool tc = false);


/// \brief Create a vector of bool using a list of named fields.
///
/// This function is used with the ResUse and Result containers,
/// which have a field_num() member function that maps a field name
/// to its position number.  So for each named field, we set the
/// bool in the vector at the corresponding position to true.
///
/// This function is used within the library to build the vector used
/// in calling the vector form of Row::equal_list(), Row::value_list(),
/// and Row::field_list().  See the "Harnessing SSQLS Internals" section
/// of the user manual to see that feature at work.

template <class Container>
void create_vector(const Container& c, std::vector<bool>& v,
		std::string s0, std::string s1, std::string s2,
		std::string s3, std::string s4, std::string s5,
		std::string s6, std::string s7, std::string s8,
		std::string s9, std::string sa, std::string sb,
		std::string sc);



/// \brief Constructs a value_list_ba
///
/// This function returns a value list that uses the 'do_nothing'
/// manipulator.  That is, the items are not quoted or escaped in any
/// way.  See value_list(Seq, const char*, Manip) if you need to
/// specify a manipulator.
///
/// \param s an STL sequence of items in the value list
/// \param d delimiter operator<< should place between items

template <class Seq>
value_list_ba<Seq, do_nothing_type0>
value_list(const Seq& s, const char* d = ",")
{
	return value_list_ba<Seq, do_nothing_type0>(s, d, do_nothing);
}


/// \brief Constructs a value_list_ba
///
/// \param s an STL sequence of items in the value list
/// \param d delimiter operator<< should place between items
/// \param m manipulator to use when inserting items into a stream

template <class Seq, class Manip>
value_list_ba<Seq, Manip>
value_list(const Seq& s, const char* d, Manip m)
{
	return value_list_ba<Seq, Manip>(s, d, m);
}


/// \brief Constructs a value_list_b (sparse value list)
///
/// \param s an STL sequence of items in the value list
/// \param d delimiter operator<< should place between items
/// \param m manipulator to use when inserting items into a stream
/// \param vb for each item in this vector that is true, the
/// corresponding item in the value list is inserted into a stream;
/// the others are suppressed

template <class Seq, class Manip>
inline value_list_b<Seq, Manip>
value_list(const Seq& s, const char* d, Manip m,
		const std::vector<bool>& vb)
{
	return value_list_b<Seq, Manip>(s, vb, d, m);
}


/// \brief Constructs a value_list_b (sparse value list)
///
/// Same as value_list(Seq&, const char*, Manip, const vector<bool>&),
/// except that it takes the bools as arguments instead of wrapped up
/// in a vector object.

template <class Seq, class Manip>
value_list_b<Seq, Manip>
value_list(const Seq& s, const char* d, Manip m, bool t0,
		bool t1 = false, bool t2 = false, bool t3 = false,
		bool t4 = false, bool t5 = false, bool t6 = false,
		bool t7 = false, bool t8 = false, bool t9 = false,
		bool ta = false, bool tb = false, bool tc = false)
{
	std::vector<bool> vb;
	create_vector(s.size(), vb, t0, t1, t2, t3, t4, t5, t6, t7, t8, t9,
				  ta, tb, tc);
	return value_list_b<Seq, Manip>(s, vb, d, m);
}

/// \brief Constructs a sparse value list
///
/// Same as value_list(Seq&, const char*, Manip, bool, bool...) but
/// without the Manip parameter.  We use the do_nothing manipulator,
/// meaning that the value list items are neither escaped nor quoted
/// when being inserted into a stream.

template <class Seq>
value_list_b<Seq, do_nothing_type0>
value_list(const Seq& s, const char* d, bool t0,
		bool t1 = false, bool t2 = false, bool t3 = false,
		bool t4 = false, bool t5 = false, bool t6 = false,
		bool t7 = false, bool t8 = false, bool t9 = false,
		bool ta = false, bool tb = false, bool tc = false)
{
	std::vector<bool> vb;
	create_vector(s.size(), vb, t0, t1, t2, t3, t4, t5, t6, t7, t8, t9,
				  ta, tb, tc);
	return value_list_b<Seq, do_nothing_type0>(s, vb, d, do_nothing);
}





/// \brief Constructs a sparse value list
///
/// Same as value_list(Seq&, const char*, Manip, bool, bool...) but
/// without the Manip or delimiter parameters.  We use the do_nothing
/// manipulator, meaning that the value list items are neither escaped
/// nor quoted when being inserted into a stream.  The delimiter is a
/// comma.  This form is suitable for lists of simple data, such as
/// integers.

template <class Seq>
value_list_b<Seq, do_nothing_type0>
value_list(const Seq& s, bool t0,
		bool t1 = false, bool t2 = false, bool t3 = false,
		bool t4 = false, bool t5 = false, bool t6 = false,
		bool t7 = false, bool t8 = false, bool t9 = false,
		bool ta = false, bool tb = false, bool tc = false)
{
	std::vector<bool> vb;
	create_vector(s.size(), vb, t0, t1, t2, t3, t4, t5, t6, t7, t8, t9,
				  ta, tb, tc);
	return value_list_b<Seq, do_nothing_type0>(s, vb, ",", do_nothing);
}


/// \brief Constructs an equal_list_ba
///
/// This function returns an equal list that uses the 'do_nothing'
/// manipulator.  That is, the items are not quoted or escaped in any
/// way when inserted into a stream.  See equal_list(Seq, Seq,
/// const char*, const char*, Manip) if you need a different
/// manipulator.
///
/// The idea is for both lists to be of equal length because
/// corresponding elements from each list are handled as pairs, but if
/// one list is shorter than the other, the generated list will have
/// that many elements.
///
/// \param s1 items on the left side of the equals sign when the
/// equal list is inserted into a stream
/// \param s2 items on the right side of the equals sign
/// \param d delimiter operator<< should place between pairs
/// \param e what operator<< should place between items in each pair;
/// by default, an equals sign, as that is the primary use for this
/// mechanism.

template <class Seq1, class Seq2>
equal_list_ba<Seq1, Seq2, do_nothing_type0>
equal_list(const Seq1& s1, const Seq2& s2, const char *d = ",",
		const char *e = " = ")
{
	return equal_list_ba<Seq1, Seq2, do_nothing_type0>(s1, s2, d,
			e, do_nothing);
}


/// \brief Constructs an equal_list_ba
///
/// Same as equal_list(Seq&, Seq&, const char*, const char*) except that
/// it also lets you specify the manipulator.  Use this version if the
/// data must be escaped or quoted when being inserted into a stream.

template <class Seq1, class Seq2, class Manip>
equal_list_ba<Seq1, Seq2, Manip>
equal_list(const Seq1& s1, const Seq2& s2, const char* d,
		const char* e, Manip m)
{
	return equal_list_ba<Seq1, Seq2, Manip>(s1, s2, d, e, m);
}


/// \brief Constructs a equal_list_b (sparse equal list)
///
/// Same as equal_list(Seq&, Seq&, const char*, const char*, Manip) except
/// that you can pass a vector of bools. For each true item in that
/// list, operator<< adds the corresponding item is put in the equal
/// list.  This lets you pass in sequences when you don't want all of
/// the elements to be inserted into a stream.

template <class Seq1, class Seq2, class Manip>
equal_list_b<Seq1, Seq2, Manip>
equal_list(const Seq1& s1, const Seq2& s2, const char* d,
		const char *e, Manip m, const std::vector<bool>& vb)
{
	return equal_list_b<Seq1, Seq2, Manip>(s1, s2, vb, d, e, m);
}


/// \brief Constructs a equal_list_b (sparse equal list)
///
/// Same as equal_list(Seq&, Seq&, const char*, const char*, Manip,
/// vector<bool>&) except that it takes boolean parameters
/// instead of a list of bools.

template <class Seq1, class Seq2, class Manip>
equal_list_b<Seq1, Seq2, Manip>
equal_list(const Seq1& s1, const Seq2& s2, const char* d,
		const char* e, Manip m, bool t0, bool t1 = false,
		bool t2 = false, bool t3 = false, bool t4 = false,
		bool t5 = false, bool t6 = false, bool t7 = false,
		bool t8 = false, bool t9 = false, bool ta = false,
		bool tb = false, bool tc = false)
{
	std::vector<bool> vb;
	create_vector(s1.size(), vb, t0, t1, t2, t3, t4, t5, t6, t7, t8,
				  t9, ta, tb, tc);
	return equal_list_b<Seq1, Seq2, Manip>(s1, s2, vb, d, e, m);
}


/// \brief Constructs a equal_list_b (sparse equal list)
///
/// Same as equal_list(Seq&, Seq&, const char*, const char*, Manip,
/// bool, bool...) except that it doesn't take the Manip argument.
/// It uses the do_nothing manipulator instead, meaning that none of
/// the elements are escaped when being inserted into a stream.

template <class Seq1, class Seq2>
equal_list_b<Seq1, Seq2, do_nothing_type0>
equal_list(const Seq1& s1, const Seq2& s2, const char* d,
		const char* e, bool t0, bool t1 = false, bool t2 = false,
		bool t3 = false, bool t4 = false, bool t5 = false,
		bool t6 = false, bool t7 = false, bool t8 = false,
		bool t9 = false, bool ta = false, bool tb = false,
		bool tc = false)
{
	std::vector<bool> vb;
	create_vector(s1.size(), vb, t0, t1, t2, t3, t4, t5, t6, t7, t8,
				  t9, ta, tb, tc);
	return equal_list_b<Seq1, Seq2, do_nothing_type0>(s1, s2, vb,
			d, e, do_nothing);
}


/// \brief Constructs a equal_list_b (sparse equal list)
///
/// Same as equal_list(Seq&, Seq&, const char*, const char*, bool,
/// bool...) except that it doesn't take the second const char*
/// argument.  It uses " = " for the equals symbol.

template <class Seq1, class Seq2>
equal_list_b<Seq1, Seq2, do_nothing_type0>
equal_list(const Seq1& s1, const Seq2& s2, const char* d, bool t0,
		bool t1 = false, bool t2 = false, bool t3 = false,
		bool t4 = false, bool t5 = false, bool t6 = false,
		bool t7 = false, bool t8 = false, bool t9 = false,
		bool ta = false, bool tb = false, bool tc = false)
{
	std::vector<bool> vb;
	create_vector(s1.size(), vb, t0, t1, t2, t3, t4, t5, t6, t7, t8,
				  t9, ta, tb, tc);
	return equal_list_b<Seq1, Seq2, do_nothing_type0>(s1, s2, vb,
			d, " = ", do_nothing);
}


/// \brief Constructs a equal_list_b (sparse equal list)
///
/// Same as equal_list(Seq&, Seq&, const char*, bool, bool...) except
/// that it doesn't take the const char* argument.  It uses a comma for
/// the delimiter.  This form is useful for building simple equals
/// lists, where no manipulators are necessary, and the default
/// delimiter and equals symbol are suitable.

template <class Seq1, class Seq2>
equal_list_b<Seq1, Seq2, do_nothing_type0>
equal_list(const Seq1& s1, const Seq2& s2, bool t0, bool t1 = false,
		bool t2 = false, bool t3 = false, bool t4 = false,
		bool t5 = false, bool t6 = false, bool t7 = false,
		bool t8 = false, bool t9 = false, bool ta = false,
		bool tb = false, bool tc = false)
{
	std::vector<bool> vb;
	create_vector(s1.size(), vb, t0, t1, t2, t3, t4, t5, t6, t7, t8,
				  t9, ta, tb, tc);
	return equal_list_b<Seq1, Seq2, do_nothing_type0>(s1, s2, vb,
			",", " = ", do_nothing);
}

} // end namespace mysqlpp

#endif // !defined(MYSQLPP_VALLIST_H)
|
|
>

<
|
|
|
|



















<
<
<
|

|
|

|


<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
|
<
<
<
<
<
<
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<

<
<
<
<
|
<
|
<
<
<
|
<
<
<
|
<
<
|
<
<
<
|
<
<
<
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
|
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
|
<
<
<
<
<
|
<
<
<

<
<
<

<
<
<
<
<
<
<
<
<
<
<
<
<
<
|
|
<
<
<
<
<
<
<
<
<
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
|
<
<
|
<
<
<
<
<
<
<
|
<
<
|
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
|
<
<
|
|
<
<
<
<
<
<
<
<
|
<
<
<
<
<
|
<
<
<
<
<
|
|

<
|
|
|
<
<
<
<
|
<
<
<
<
<

<
<
<
<
<
<
<
<
<
<
<
<
|
<
<
|
|
<
<
<
<
<
<
<
<
<
|
<
<
<
<
<
|

<
<
<
<
<
<
<
<
<
<
<

<
<
<
<
<
<
<
|
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
|
<
<
|
|
<
<
<
<
<
<
<
<
|
<
<
<
<
<
<
<
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
|
|
<
|
<
<
<
<
|
<
<
<
<
<
<
<
<
<
<
<
<
<
|
>
>
>
|
<
<
<
<
<
<
<
<
|
<
<
<
<
<
<
<
|
<
<
<
<
|
|
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<

<
<
<
<
<
<
<
<
|
|
<
<
<
<
<
|
<
<
<
<
<
<
<
|
|
<
<
<
<
<
<
<
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
|
<
<
<
<
<
|
|
<
<
<
<
<
<
|
<
<
<
<
<
<
<
<
|
<
<
<
<
<
<
|
|
<
<
<
<
<
|
<
<
<
<
<
<
<
<
<
<
<
<
<

<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
1
2
3
4

5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27



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


56







57


58
59
























60


61
62








63





64





65
66
67

68
69
70




71





72












73


74
75









76





77
78











79







80
81




























82


83
84








85







86



















87
88

89




90













91
92
93
94
95








96







97




98
99
100




















101








102
103





104







105
106







107























108





109
110






111








112






113
114





115













116




























/***********************************************************************
 printdata.cpp - Utility functions for printing out data in common
    formats, required by most of the example programs.


 Copyright (c) 1998 by Kevin Atkinson, (c) 1999-2001 by MySQL AB, and
 (c) 2004-2007 by Educational Technology Resources, Inc.  Others may
 also hold copyrights on code in this file.  See the CREDITS file in
 the top directory of the distribution for details.

 This file is part of MySQL++.

 MySQL++ is free software; you can redistribute it and/or modify it
 under the terms of the GNU Lesser General Public License as published
 by the Free Software Foundation; either version 2.1 of the License, or
 (at your option) any later version.

 MySQL++ is distributed in the hope that it will be useful, but WITHOUT
 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
 License for more details.

 You should have received a copy of the GNU Lesser General Public
 License along with MySQL++; if not, write to the Free Software
 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
 USA
***********************************************************************/




#include "printdata.h"

#include <iostream>
#include <iomanip>

using namespace std;





















//// print_stock_header ////////////////////////////////////////////////






// Display a header suitable for use with print_stock_rows().




















































void

print_stock_header(int rows)



{



	cout << "Records found: " << rows << endl << endl;


	cout.setf(ios::left);



	cout << setw(31) << "Item" <<



			setw(10) << "Num" <<
























			setw(10) << "Weight" <<
			setw(10) << "Price" <<


















			"Date" << endl << endl;





}






















//// print_stock_row ///////////////////////////////////////////////////
// Print out a row of data from the stock table, in a format compatible









// with the header printed out in the previous function.





















































void







print_stock_row(const mysqlpp::sql_char& item, mysqlpp::sql_bigint num,


		mysqlpp::sql_double weight, mysqlpp::sql_decimal price,
		const mysqlpp::sql_date& date)
























{


	cout << setw(30) << item << ' ' <<
			setw(9) << num << ' ' <<








			setw(9) << weight << ' ' <<





			setw(9) << price << ' ' <<





			date << endl;
}



//// print_stock_row ///////////////////////////////////////////////////
// Take a Row from the example 'stock' table, break it up into fields,




// and call the above version of this function.


















void


print_stock_row(const mysqlpp::Row& row)
{









	print_stock_row(string(row[0]), row[1], row[2], row[3], row[4]);





}




















//// print_stock_rows //////////////////////////////////////////////////
// Print out a number of rows from the example 'stock' table.































void
print_stock_rows(mysqlpp::StoreQueryResult& res)








{







	print_stock_header(res.size());




















	// Use the StoreQueryResult class's read-only random access iterator to walk

	// through the query results.




	mysqlpp::StoreQueryResult::iterator i;













	for (i = res.begin(); i != res.end(); ++i) {
		// Notice that a dereferenced result iterator can be converted
		// to a Row object, which makes for easier element access.
		print_stock_row(*i);
	}








}













//// print_stock_table /////////////////////////////////////////////////
// Simply retrieve and print the entire contents of the stock table.





























void
print_stock_table(mysqlpp::Query& query)





{







	// Reset query object to its pristine state in case it's been used
	// before by our caller for template queries.







	query.reset();





























	// Build the query itself, and show it to the user
	query << "select * from stock";






	cout << "Query: " << query << endl;















	// Execute it, and display the results
	mysqlpp::StoreQueryResult res = query.store();





	print_stock_rows(res);













}




























Changes to lib/wnp_connection.cpp.









1
2

3
4
5
6
7



8
9
10
11
12
13






14





15
16
17
18




19
20





21

22

23
24

25
26
27
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
56





57
58







59
60
61


62



63



64






65
66
67
68
69
70




71
72

73










/***********************************************************************
 wnp_connection.cpp - Implements the WindowsNamedPipeConnection class.


 Copyright (c) 2007-2008 by Educational Technology Resources, Inc.
 Others may also hold copyrights on code in this file.  See the
 CREDITS.txt file in the top directory of the distribution for details.




 This file is part of MySQL++.

 MySQL++ is free software; you can redistribute it and/or modify it
 under the terms of the GNU Lesser General Public License as published
 by the Free Software Foundation; either version 2.1 of the License, or
 (at your option) any later version.












 MySQL++ is distributed in the hope that it will be useful, but WITHOUT
 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
 License for more details.





 You should have received a copy of the GNU Lesser General Public





 License along with MySQL++; if not, write to the Free Software

 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301

 USA
***********************************************************************/


#define MYSQLPP_NOT_HEADER
#include "common.h"
#include "wnp_connection.h"



#include "exceptions.h"



using namespace std;

namespace mysqlpp {

static const char* common_complaint =
		"WindowsNamedPipeConnection only works on Windows";






bool
WindowsNamedPipeConnection::connect(const char* db, const char* user,



		const char* pass)
{
#if defined(MYSQLPP_PLATFORM_WINDOWS)
	return Connection::connect(db, ".", user, pass);
#else
	(void)db;
	(void)user;
	(void)pass;
	error_message_ = common_complaint;
	if (throw_exceptions()) {
		throw ConnectionFailed(error_message_.c_str());
	}
	else {



		return false;
	}





#endif
}









bool


WindowsNamedPipeConnection::is_wnp(const char* server)



{



#if defined(MYSQLPP_PLATFORM_WINDOWS)






	return server && (strcmp(server, ".") == 0);
#else
	(void)server;
	return false;
#endif
}





} // end namespace mysqlpp




>
>
>
>
>
>
>
>
|
<
>

<
<
<

>
>
>
|

<
<
<
<
>
>
>
>
>
>

>
>
>
>
>
|
<
|
<
>
>
>
>

|
>
>
>
>
>
|
>
|
>
|
<
>

<
<
<
>
>

<
>

>
|

|

|
<
>
>
>
>
|

|
|
>
>
>
|
|
<
<
<
|
|
|
<
|
<
|
|
>
>
>
|
|
>
>
>
>
>
|
|
>
>
>
>
>
>
>


<
>
>
|
>
>
>
|
>
>
>
|
>
>
>
>
>
>
|
<
<
<
<
|
>
>
>
>

<
>

>
>
1
2
3
4
5
6
7
8
9

10
11



12
13
14
15
16
17




18
19
20
21
22
23
24
25
26
27
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
56
57
58
59
60

61
62
63
64
65
66
67
68
69
70
71
72
73



74
75
76

77

78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100

101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118




119
120
121
122
123
124

125
126
127
128
What It Is
~~~~~~~~~~
    MySQL++ is a C++ wrapper for MySQL's C API.  It is built around STL
    principles, to make dealing with the database as easy as dealing
    with an STL container.  MySQL++ relieves the programmer of dealing
    with cumbersome C data structures, generation of repetitive SQL
    statements, and manual creation of C++ data structures to mirror
    the database schema.


    Its home page is http://tangentsoft.net/mysql++/





Prerequisites
~~~~~~~~~~~~~
    To build MySQL++, you must have the MySQL C API development
    files installed.





    On Unixy systems (Linux, Mac OS X, Cygwin, *BSD, Solaris...),
    the MySQL development files are installed if you build MySQL
    from source.  If you installed MySQL as a binary package, then
    the development files are often packaged separately from the
    MySQL server itself.  It's common for the package containing the
    development files to be called something like "MySQL-devel".

    If you're building on Windows with Visual C++ or MinGW, you
    need to install the native Win32 port of MySQL from mysql.com.
    The development files are only included with the "complete"
    version of the MySQL installer, and some versions of this
    installer won't actually install them unless you do a custom
    install.  Another pitfall is that MySQL++'s project files assume

    that you've installed the current General Availability release of

    MySQL (v5.0 right now) and it's installed in the default location.
    If you've installed a different version, or if MySQL Inc. changes
    the default location (which they seem to do regularly!) you'll have
    to adjust the link and include file paths in the project settings.


Additional Things to Read
~~~~~~~~~~~~~~~~~~~~~~~~~
    Each major platform we support has a dedicated README-*.txt
    file for it containing information specific to that platform.
    Please read it.

    For authorship information, see the CREDITS.txt file.

    For license information, see the COPYING.txt file.


    If you want to change MySQL++, see the HACKERS.txt file.




    You should have received a user manual and a reference manual
    with MySQL++.  If not, you can read a recent version online:


        http://tangentsoft.net/mysql++/doc/

    Search the MySQL++ mailing list archives if you have more
    questions:

        http://lists.mysql.com/plusplus/



Building the Library
~~~~~~~~~~~~~~~~~~~~
    MySQL++ uses Bakefile (http://bakefile.org/) to generate
    platform-specific project files and makefiles from a single set
    of input files.  We currently support these build systems:

    autoconf:
        For Unixy platforms, including Linux, Mac OS X, and Cygwin, in
        addition to the "real" Unices.  See README-Unix.txt for general
        instructions.  Supplementary platform-specific details are
        in README-Cygwin.txt, README-Linux.txt, README-Mac-OS-X.txt,
        and README-Solaris.txt.




    MinGW:
        We ship Makefile.mingw for MinGW.  It currently only builds the
        static version of the library for technical reasons.  This has

        licensing ramifications.  See README-MinGW.txt for details.


    Visual C++:
        We ship Visual Studio 2003, 2005, and 2008 project files.
        No older version of Visual C++ will build MySQL++, due to
        compiler limitations.  See README-Visual-C++.txt for more
        details.

    Xcode:
        We ship an Xcode v2 project file.  It hasn't been tested
        much yet, since the autoconf method works just fine on OS X.
        As a result, we need both success and failure reports on the
        mailing list.  See README-Mac-OS-X.txt for more information.


Example Programs
~~~~~~~~~~~~~~~~
    You may want to try out the programs in the examples subdirectory
    to ensure that the MySQL++ API and your MySQL database are both
    working properly.  Also, these examples give many examples of
    the proper use of MySQL++.  See README-examples.txt for further
    details.



Unsupported Compliers
~~~~~~~~~~~~~~~~~~~~~
    If you're on Windows but want to use some other compiler besides
    Visual C++ or GCC, you are currently on your own.  There have
    been past efforts to port MySQL++ to other Windows compilers,
    but for one reason or another, all of these ports have died.

    On Unixy systems, GCC still works best.  "Native" compilers and
    third-party compilers may work, but you're on your own to get
    it working.

    We have nothing in particular against these unsupported systems.
    We just lack the time and resources to support everything
    ourselves.  If you are sufficiently motivated to get MySQL++
    working on one of these alternate systems, see the HACKERS.txt
    file first for guidance.  If you follow the advice in that file,
    your patch will be more likely to be accepted.






If You Want to Hack on MySQL++...
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    If you intend to change the library or example code, please read
    the HACKERS.txt file.


    If you want to change the user manual, read doc/userman/README.txt

    If you want to change the reference manual, see the Doxygen manual:
    http://www.stack.nl/~dimitri/doxygen/manual.html

Changes to lib/wnp_connection.h.

1
2
3
4

5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
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
56

57






58
59




60
61
62

63



64
65





66









67

68


69











70

71


72



73
74
75









76
77
78
79

80

81





82




83
84
85
86



87
88





89
90





91
92





















93

94
95





96
97





98
99
















100








101















102
103





104








105




106
107





108
109
110
111
112
/// \file wnp_connection.h
/// \brief Declares the WindowsNamedPipeConnection class.

/***********************************************************************

 Copyright (c) 2007-2008 by Educational Technology Resources, Inc.
 Others may also hold copyrights on code in this file.  See the
 CREDITS.txt file in the top directory of the distribution for details.

 This file is part of MySQL++.

 MySQL++ is free software; you can redistribute it and/or modify it
 under the terms of the GNU Lesser General Public License as published
 by the Free Software Foundation; either version 2.1 of the License, or
 (at your option) any later version.

 MySQL++ is distributed in the hope that it will be useful, but WITHOUT
 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
 License for more details.

 You should have received a copy of the GNU Lesser General Public
 License along with MySQL++; if not, write to the Free Software
 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
 USA
***********************************************************************/

#if !defined(MYSQLPP_WNP_CONNECTION_H)
#define MYSQLPP_WNP_CONNECTION_H



#include "connection.h"




namespace mysqlpp {







/// \brief Specialization of \c Connection for Windows named pipes
///








/// This class just simplifies the connection creation interface of
/// \c Connection.  It does not add new functionality.






class MYSQLPP_EXPORT WindowsNamedPipeConnection : public Connection
{





public:
	/// \brief Create object without connecting it to the MySQL server.





















	WindowsNamedPipeConnection() :


















	Connection()
	{

	}










	/// \brief Create object and connect to database server over Windows









	/// named pipes in one step.



	///
	/// \param db name of database to use








	/// \param user user name to log in under, or 0 to use the user
	///		name the program is running under






	/// \param password password to use when logging in
	WindowsNamedPipeConnection(const char* db, const char* user = 0,
			const char* password = 0) :

	Connection()






	{
		connect(db, user, password);




	}

	/// \brief Establish a new connection using the same parameters as

	/// an existing connection.



	///
	/// \param other pre-existing connection to clone





	WindowsNamedPipeConnection(const WindowsNamedPipeConnection& other) :









	Connection(other)

	{


	}













	/// \brief Destroy object


	~WindowsNamedPipeConnection() { }




	/// \brief Connect to database after object is created.
	///









	/// It's better to use the connect-on-create constructor if you can.
	/// See its documentation for the meaning of these parameters.
	///
	/// If you call this method on an object that is already connected

	/// to a database server, the previous connection is dropped and a

	/// new connection is established.





	bool connect(const char* db = 0, const char* user = 0,




			const char* password = 0);

	/// \brief Check that given string denotes a Windows named pipe
	/// connection to MySQL



	///
	/// \param server the server address





	///
	/// \return false if server address does not denote a Windows





	/// named pipe connection, or we are not running on Windows
	static bool is_wnp(const char* server);























private:
	/// \brief Provide uncallable versions of the parent class ctors we





	/// don't want to provide so we don't get warnings about hidden
	/// overloads with some compilers





	WindowsNamedPipeConnection(bool) { }
	WindowsNamedPipeConnection(const char*, const char*, const char*,
















			const char*, unsigned int) { }
























	/// \brief Explicitly override parent class version so we don't get
	/// complaints about hidden overloads with some compilers





	bool connect(const char*, const char*, const char*, const char*,








			unsigned int) { return false; }




};







} // end namespace mysqlpp

#endif // !defined(MYSQLPP_WNP_CONNECTION_H)

|
|

<
>
|
|
|



















<
|
>

>
|
>
>
>



>
>
>
>
>
>
|
|
>
>
>
>
>
>
>
>
|
|
>
>
>
|
>
>
|
|
>
>
>
>
>
|
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
|
>
|
>
>
>
>
>
>
>
>
>

|
>
>
>
>
>
>
>
>
>
|
>
>
>
|
|
>
>
>
>
>
>
>
>
|
|
>
>
>
>
>
>
|
|
<
>
|
>
>
>
>
>
>
|
|
>
>
>
>
|

|
>
|
>
>
>
|
|
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
|
>
|
>
>
|
>
>
>
>
>
>
>
>
>
>
>
|
>
|
>
>
|
>
>
>
|
|
|
>
>
>
>
>
>
>
>
>
|
|
<
<
>
|
>
|
>
>
>
>
>
|
>
>
>
>
|

|
|
>
>
>
|
|
>
>
>
>
>
|
|
>
>
>
>
>
|
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
|
|
>
>
>
>
>
|
|
>
>
>
>
>
|
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
|
>
>
>
>
>
|
>
>
>
>
>
>
>
>
|
>
>
>
>
|

>
>
>
>
>



<
<
1
2
3

4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26

27
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
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
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
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
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
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
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
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
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
372
373
374
375
376
377
378
379
380
381
382
383
384
385


/***********************************************************************
 connection.cpp - Implements the Connection class.


 Copyright (c) 1998 by Kevin Atkinson, (c) 1999-2001 by MySQL AB, and
 (c) 2004-2008 by Educational Technology Resources, Inc.  Others may
 also hold copyrights on code in this file.  See the CREDITS.txt file
 in the top directory of the distribution for details.

 This file is part of MySQL++.

 MySQL++ is free software; you can redistribute it and/or modify it
 under the terms of the GNU Lesser General Public License as published
 by the Free Software Foundation; either version 2.1 of the License, or
 (at your option) any later version.

 MySQL++ is distributed in the hope that it will be useful, but WITHOUT
 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
 License for more details.

 You should have received a copy of the GNU Lesser General Public
 License along with MySQL++; if not, write to the Free Software
 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
 USA
***********************************************************************/


#define MYSQLPP_NOT_HEADER
#include "connection.h"

#include "dbdriver.h"
#include "query.h"
#include "result.h"

using namespace std;

namespace mysqlpp {

Connection::Connection(bool te) :
OptionalExceptions(te),
driver_(new DBDriver()),
copacetic_(true)
{
}


Connection::Connection(const char* db, const char* server,
		const char* user, const char* password, unsigned int port) :
OptionalExceptions(),
driver_(new DBDriver()),
copacetic_(true)
{
	connect(db, server, user, password, port);
}


Connection::Connection(const Connection& other) :
OptionalExceptions(),
driver_(new DBDriver(*other.driver_))
{
	copy(other);
}


Connection::~Connection()
{
	disconnect();
	delete driver_;
}


void
Connection::build_error_message(const char* core)
{
	error_message_ = "Can't ";
	error_message_ += core;
	error_message_ += " while disconnected";
}


std::string
Connection::client_version() const
{
	return driver_->client_version();
}


bool
Connection::connect(const char* db, const char* server,
		const char* user, const char* password, unsigned int port)
{
	// Figure out what the server parameter means, then try to establish
	// the connection.
	error_message_.clear();
	string host, socket_name;
	copacetic_ = parse_ipc_method(server, host, port, socket_name) &&
			driver_->connect(host.c_str(),
			(socket_name.empty() ? 0 : socket_name.c_str()), port, db,
			user, password);

	// If it failed, decide how to tell the user
	if (!copacetic_ && throw_exceptions()) {
		throw ConnectionFailed(error(), errnum());
	}
	else {
		return copacetic_;
	}
}


bool
Connection::connected() const
{
	return driver_->connected();
}


void
Connection::copy(const Connection& other)
{
	error_message_.clear();
	set_exceptions(other.throw_exceptions());
	driver_->copy(*other.driver_);
}


ulonglong
Connection::count_rows(const std::string& table)
{
	error_message_.clear();
	Query q(this, throw_exceptions());
	q << "SELECT COUNT(*) FROM `" << table << '`';
	if (StoreQueryResult res = q.store()) {
		return res[0][0];
	}
	else {
		return 0;
	}
}


bool
Connection::create_db(const std::string& db)
{
	error_message_.clear();
	Query q(this, throw_exceptions());
	q << "CREATE DATABASE `" << db << '`';
	return q.exec();
}


void
Connection::disconnect()
{
	error_message_.clear();
	driver_->disconnect();
}



bool
Connection::drop_db(const std::string& db)
{
	error_message_.clear();
	Query q(this, throw_exceptions());
	q << "DROP DATABASE `" << db << '`';
	return q.exec();
}


int
Connection::errnum()
{
	return driver_->errnum();
}


const char*
Connection::error() const
{
	return error_message_.size() ? error_message_.c_str() : driver_->error();
}


std::string
Connection::ipc_info() const
{
	return driver_->ipc_info();
}


bool
Connection::kill(unsigned long tid) const
{
	error_message_.clear();
	return driver_->kill(tid);
}


Connection&
Connection::operator=(const Connection& rhs)
{
	copy(rhs);
	return *this;
}


bool
Connection::parse_ipc_method(const char* server, std::string& host,
		unsigned int& port, std::string& socket_name)
{
	// NOTE: This routine has no connection type knowledge.  It can only
	// recognize a 0 value for the server parameter.  All substantial
	// tests are delegated to our specialized subclasses, which figure
	// out what kind of connection the server address denotes.  We do
	// the platform-specific tests first as they're the most reliable.
	
	if (server == 0) {
		// Just take all the defaults
		return true;
	}
	else if (WindowsNamedPipeConnection::is_wnp(server)) {
		// Use Windows named pipes
		host = server;
		return true;
	}
	else if (UnixDomainSocketConnection::is_socket(server)) {
		// Use Unix domain sockets
		socket_name = server;
		return true;
	}
	else {
		// Failing above, it can only be some kind of TCP/IP address.
		host = server;
		return TCPConnection::parse_address(host, port, error_message_);
	}
}




bool
Connection::ping()
{
	if (connected()) {
		error_message_.clear();
		return driver_->ping();
	}
	else {
		// Not connected, and we've forgotten everything we need in
		// order to re-connect, if we once were connected.
		build_error_message("ping database server");
		return false;
	}
}


int
Connection::protocol_version() const
{
	return driver_->protocol_version();
}


Query
Connection::query(const char* qstr)
{
	return Query(this, throw_exceptions(), qstr);
}


Query
Connection::query(const std::string& qstr)
{
	return query(qstr.c_str());
}


bool
Connection::select_db(const std::string& db)
{
	error_message_.clear();
	if (connected()) {
		if (driver_->select_db(db.c_str())) {
			return true;
		}
		else {
			if (throw_exceptions()) {
				throw DBSelectionFailed(error(), errnum());
			}
			return false;
		}
	}
	else {
		build_error_message("select a database");
		if (throw_exceptions()) {
			throw DBSelectionFailed(error_message_.c_str());
		}
		return false;
	}
}


std::string
Connection::server_status() const
{
	return driver_->server_status();
}


std::string
Connection::server_version() const
{
	return driver_->server_version();
}


bool
Connection::set_option(Option* o)
{
	const std::type_info& oti = typeid(*o);
	if (driver_->set_option(o)) {
		error_message_.clear();
		return true;
	}
	else {
		error_message_ = driver_->error();
		if (throw_exceptions()) {
			throw BadOption(error_message_, oti);
		}
		return false;
	}
}


bool
Connection::shutdown()
{
	error_message_.clear();
	if (connected()) {
		if (driver_->shutdown()) {
			return true;
		}
		else {
			if (throw_exceptions()) {
				throw ConnectionFailed(error(), errnum());
			}
			return false;
		}
	}
	else {
		build_error_message("shutdown database server");
		if (throw_exceptions()) {
			throw ConnectionFailed(error_message_.c_str());
		}
		return false;
	}
}


bool
Connection::thread_aware()
{
	return DBDriver::thread_aware();
}


void
Connection::thread_end()
{
	DBDriver::thread_end();
}


unsigned long
Connection::thread_id()
{
	return driver_->thread_id();
}


bool
Connection::thread_start()
{
	return DBDriver::thread_start();
}

} // end namespace mysqlpp



Changes to osver.

1
2
3
4



5

6




7



8
9





10

11

12
13
14




15

16
#!/bin/sh
if grep Red /etc/issue > /dev/null 2>&1
then
	echo -n rh



	grep Red /etc/issue |cut -f5 -d' '

elif grep Fedora /etc/issue > /dev/null 2>&1




then



	echo -n fc
	grep Fedora /etc/issue |cut -f4 -d' '





elif grep CentOS /etc/issue > /dev/null 2>&1

then

	echo -n el
	grep CentOS /etc/issue |cut -f3 -d' ' |cut -f1 -d.
else




	echo UNKNOWN

fi
|
|
|
|
>
>
>
|
>
|
>
>
>
>
|
>
>
>
|
|
>
>
>
>
>
|
>
|
>
|
<
|
>
>
>
>
|
>
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30

31
32
33
34
35
36
37
38
/***********************************************************************
 mysql++.cpp - Implements functions dealing with the library itself,
	as opposed to individual features of the library.

 Copyright (c) 2007 by Educational Technology Resources, Inc.
 Others may also hold copyrights on code in this file.  See the CREDITS
 file in the top directory of the distribution for details.

 This file is part of MySQL++.

 MySQL++ is free software; you can redistribute it and/or modify it
 under the terms of the GNU Lesser General Public License as published
 by the Free Software Foundation; either version 2.1 of the License, or
 (at your option) any later version.

 MySQL++ is distributed in the hope that it will be useful, but WITHOUT
 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
 License for more details.

 You should have received a copy of the GNU Lesser General Public
 License along with MySQL++; if not, write to the Free Software
 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
 USA
***********************************************************************/

#include "mysql++.h"

namespace mysqlpp {


unsigned int 
get_library_version()
{
	return MYSQLPP_HEADER_VERSION;
}

} // end namespace mysqlpp

Deleted pretty.pl.

1
sql++pretty
<


Changes to rebake.bat.

1































































































































































































2

@echo on































































































































































































bakefile_gen %*

|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
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
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
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
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
191
192
193
194
C Version\s3.0.6
D 2008-08-18T00:50:17.000
F Bakefiles.bkgen 3fee60e49b8262d90c478e5b1957ef0c2401ae26d58e467f7a126ab0a416056c
F COPYING.txt c943babbd1de963894a9ba8583e8f50cdc7a6ab7c0522a0251c8cd21caa9f672
F CREDITS.txt 6f60a0cf1a03e89154c9696865d3f9208d5ec4f696da2e1f486d74bf50e029bb
F ChangeLog 135d0e4f44544205c75889e8e65d93442809e1c1542136adc1b55b5417833bad
F HACKERS.txt 35a8135c0ded23b6e5a08c3363052f155dbdc275d32cc78b96fc8d42fc0590ae
F INSTALL.txt 34f34084bb61b1092c2baaba90fb48723010dbe50d09acb5b170820aafad41b5
F LICENSE.txt b128a66dab867923153b3de29a9c06726e4ce0fafa4e38ce095df3f3e0bb631d
F Makefile.mingw 05bcff79449ad066d316d480405c85f45c435ea0947e98d551b07ebe3b9cae66
F Makefile.simple 0b1192f54c14fa7c421cc20e09fd8c1c871156818d14efcaa32626fe50729d3d
F README-Cygwin.txt ad68dc29f6dc26bb6fb6d4e23d8571a46eb1e84558929abec5a0cc914f1e3f2b
F README-Linux.txt 418e01796ed0bc9b54ac87aaf2d38da33845e26c10fb04e77a9e10ad2ee01fb2
F README-Mac-OS-X.txt d83329e4eab435839e5bd5330d1ae73e44de4de61f539723beb1e802602549f8
F README-MinGW.txt 167c365d0f9c8658aec4b9a50b9eae2f1d49cb83aa2b03626e02fe62fee0347c
F README-Solaris.txt 17bab66b3620f84a1b18c99a88abf447d46ad915888485e8dc4ee6a3c7898c9e
F README-Unix.txt d325e5a78f039e514fddf63d3d65912ad8492c28829fa211101101d4f73eb7f2
F README-Visual-C++.txt 209e07cf21f6b91156837a32adb8974368063ed87e007fbf9cf11b78e2703cd4
F README-examples.txt 1e9e6a1f8602029653bc44120a36c1e50fe583b5489639081f745255f18400a3
F README.txt beb3b1247585cc45b04d82a823dd81d43f81ff6e8a468d956d3a5d5b42fe93dd
F Wishlist 34fe1737ada809d47b6091b554a58c5c76d5663aa5c62bdd250645469d77f938
F bk-deps 1c32f89b39fcf81ecc460c9cd53180bf7100218d1370eec6ce03744730427a3b x
F bmark.txt 22ff7aee26aa77287c13dade94e3011df708d54726d7453b6a2b2d568916160c
F bootstrap b575e3635dab3d11176038520e51853d7afd8e28396de3a16d360d463e8c642f x
F bootstrap.bat 8e5cedcafa6de252300d88f701be1142d1f2b0826eb5a381dd29f0e9cbbd0f64
F cleanmf e385426a032ada497be42ff7504ef1fffcccd34635af530c25f19e2f209ec653 x
F config.h.in cf4d9486876d4c8f048931316618bde9015a2e77bf521ec3f758cedd4c5a319f
F config/acx_pthread.m4 8a9dbf4783b282f82c062edac20886e75e0ef9d555ac59b0dad68f1559a3a460
F config/autoconf_inc.m4 cc4ec1eea384175f2f9540273597f7fe7cdc1e3def8a6abf34dc80ab439822d9
F config/libm.m4 de3dcf0b6e8149f13c9e26dcdeaf25bf5b40fa3993546835b29c0a3be6ee63ea
F config/localtime_r.m4 8ba2bda9bdf152d8f901180b2eec716f75c381c5ed2d98666f4f0cfe29152256
F config/mysql++.m4 ddf74cd79b4daca86e81ef036dd7251c2b4490018bace836139d3f9d1e0aee92
F config/mysql_loc.m4 feb70ad98895cf41d32d45698d43a86b8729d0146f174b8356d267dd30e7752e
F config/mysql_ssl.m4 82d5c48515915eec8c2c817216a31b1f5a167382b150e547a306e5715905ce57
F config/socket_nsl.m4 6dd364d066feec0abf2b2bcdd377710010c459d3c6fbedad77a20f38997c7de2
F config/stl_slist.m4 614e5c3929b7b506b1f61ce6a4f089a5ef5acc049a0920963a32dd2bd11ad7c1
F configure.ac 609335ed99e8615f64da789b7858b7da468857c5330428a18d6a82bee6db92f8
F doc/README-devel-RPM.txt d920bb8de3af6578f5cbe1d41b53010b3e0c37163ec8226aa708d1aab869ec83
F doc/README-manuals-RPM.txt 12316b39e05f17d22d378647a574c7f6d1a12bca86ca75c54e761555b9f34763
F doc/ssqls-pretty d5f23af891a27583871e0bc1dd3c3df1f43eb6ce02e8ba06f69c3b5a82efedc5 x
F doc/userman/Makefile 9e939de82cf6e8c0bebe232a2c323a3dbfe1ddd9b2ab66b54f4ff89a05078adc
F doc/userman/breakages.dbx cd594f29c0004353b25ab7d0ea44c22bf0f4f853104539c90fd6ded63c516b97
F doc/userman/common.xsl 9add6137307259e12d69cc2b6fd099adb66a6a9e414ec0a52f5ea6dfd5665f01
F doc/userman/configuration.dbx 4a1261a7408486392541f1d19936e928426231046e0d932798048a489c28f97a
F doc/userman/fo.xsl ac5397b661eb25507f9709f3e420b0d6be899d5bbed5c2cbff5c76b1a09ceadc
F doc/userman/html.xsl acaffa4de9387b095cb9bc22508d5bebfeccb5c4c506bb067ca0dc881536b554
F doc/userman/intro.dbx 89be0767f0cd67c71b0001bb91cc8d88212f5e22505d99a9c4c86f6b0be90d0f
F doc/userman/licenses.dbx 5210e399c6574fc3436a7a5395b3c4c1bc777943392565ac403b4e076b2bff43
F doc/userman/mktxt d7fb06e2c293cb0106ec5ba5508757022740f07e79f96065925735fa11506374 x
F doc/userman/overview.dbx 664e82537fe76d75e5b9d7bf334085ac2f7222790dc4454beae347fa4f36ff5a
F doc/userman/section-template.dbx 2753f0306f13cd26d040d08e35744d96418569e03c607ce7b18aecaa54964dda
F doc/userman/ssqls.dbx 6d3df78e44b59d8a2db81d5229c271b8df7d3007a92c522a0408d14ddf536639
F doc/userman/threads.dbx b135799be0d6b1978aa681cc5e8516b038b50e808c29118a393eb2731069c3c6
F doc/userman/tquery.dbx 7b8ffd53c05a363bfbabe5469d0bbdd4c6ed346cfe63eedfccb150cff67209e6
F doc/userman/tutorial.dbx 2ecf913b6418116887a1af51289a28bb11b1ead6588c0e439a5fd2912e963414
F doc/userman/unicode.dbx 17d3c6f0e9855522df4c02077598e07760f46cc29d5d3657766eb1d92f25e9d3
F doc/userman/userman.dbx dfb7ef58252b1b535d56c5e1621883a18c9d9867ca8ee50086a276298476ae91
F doc/userman/userman.dbx.in b7cd6628193b6d83caa192879b8a6988a664e9da08841e9db958b44ca64b9dec
F dtest 14b5d6ee3fbea358f896befa948871f89eddde5758ed62bc84bf2690b3c894f4 x
F examples/cgi_jpeg.cpp b73d35e9142c44b0bbb0e1e0998f966e2e9a1641bd369ba9e9a505ea6e04fa29
F examples/cmdline.cpp 47e3c7fa7501c4071d0b168333b71425de6813fdac7eb97987e1b0ed5d52dfb1
F examples/cmdline.h ccc42bda52f6c1d9b3916d48d4f9cdf532744f0871bb2c3e7338604f6ad66991
F examples/cpool.cpp 750f364adbdfa20835e82d33efef73042ac40a4c6df1d77ec0e48bfa89ad6e4b
F examples/dbinfo.cpp 82141a616ea4964587ed84aab0d64d23ac0c8af337238f6cf00696abd78ff759
F examples/deadlock.cpp 4c37439697898dcf69cb8bf553140c5406bcc17d6be71468275a62840bb4750b
F examples/fieldinf.cpp 01bb7da9942f010362847bd4ee71e5802a0b00390751597dd6e3ef1c6f5093e0
F examples/for_each.cpp d7996fbf93148e81e61bebbff080536d0e3325bbff93573751cecfe142893793
F examples/load_jpeg.cpp 5e7b0060de23337da0f17f3f0fe98c2cde524871895d23f46a44d59c59a66cdc
F examples/logo.jpg b551f2a4609684c83c17acc32faa08af659df397aba70fe7e0f12de82c4bc934
F examples/multiquery.cpp ac0eab84d3416960e71ba4f48da0a78cdfac62e9606acf7bc326ba7e8462d7aa
F examples/printdata.cpp 8d7e90ce90d92ef4f612373ee67622373b02568ddc329a55d2d7e7cb87f8fe37
F examples/printdata.h 7d284baafdc5fcaaa2aab08d8a1a947f73fc344293939c62bcf7f249edbf1b7d
F examples/resetdb.cpp 35f0d7450e6547866287d7f8d6de01c71c3c1fc4c406356b588cfee0c6d6f4bf
F examples/simple1.cpp 33adb7f560a879fbd9ec237f8cd072ffe1d7b4c7a086bb55607627f166851790
F examples/simple2.cpp 957b2e15b818971c925ad87211962c865a3903f79959ab3a92ff423b8cf5a3fc
F examples/simple3.cpp 6d9c6022a956b995b514b1e04c950f347ce14e8d26c141e5e3703b16672c5a13
F examples/ssqls1.cpp eb2a52bb67c7463681fbc6445eabe78ee953e3f86afbc8a6c6c9848af1de12bc
F examples/ssqls2.cpp 062fe89b3e6410b65cf7f3c47cfac491c9a0446072f085e917226d3518c49022
F examples/ssqls3.cpp 38b01d94fa588bd7fce4bd8270bbde10753f5673f1d8add16c8412b9fed21df8
F examples/ssqls4.cpp f68e71b10246544693ad1ac70cfca902e03688c41d18d705a05462957698dc7c
F examples/ssqls5.cpp a0df0abcaed1e9955985c778e21a209aa04d198cdac115a7855b908ef5d3a56a
F examples/stock.h 0abb5b713dd6b737de2446a835f235ba120404d02e1772422ffdcb69eaf2e092
F examples/store_if.cpp 07a1587760523fe4cb3a3d704123eccd368a41636cc7d1c4c24d271ee897ee2c
F examples/threads.h 8a83f13a1d5d25d93e5d6d4b90b6d07960e70f86cffaa619863ef80847cb439d
F examples/tquery1.cpp 731d8bb51c0830a5bf787f52691bddd90232fcbc307300aa38d7ec47e25c620c
F examples/tquery2.cpp a72cf35ea3ce1b5194593b1ea34dab584699ddd2be1aad3fd9f40d5e5ff5fa54
F examples/tquery3.cpp dd6858492ee1c31f0ad746e00b5a2e70eeb9fb678f6c359b21ee53ea6d32cdbd
F examples/transaction.cpp 584f8334c1fef212836f4323cb5bf886b09a58f7cac2975811f3925678b646a0
F examples/vstudio/mfc/mfc.cpp c843a64bfb180dc571c744a93e658250c5ddde524cac35f3bc33d98be01ff11e
F examples/vstudio/mfc/mfc.h 1836e16493d6bf71542b779da943184b70049ca1398ffc99900985bb9280cee8
F examples/vstudio/mfc/mfc.rc 7f893118cb86cbcbf8a4d4d30fd5f122d7b7916895aba82327c770354dbd842a
F examples/vstudio/mfc/mfc_dlg.cpp 921ee6a24fd5cb3a9a943a15e90c0335d911db247cc1b7b1cf2e20c46c48dee0
F examples/vstudio/mfc/mfc_dlg.h 32431938f8f31e8e8859384d867f5004b94f5c3256a700844dfbac705e4d2e9c
F examples/vstudio/mfc/resource.h ca71f958b51bf17dfbba0d1591211efe36187ef869b6bff5e0dc9a59cf40a2f6
F examples/vstudio/mfc/stdafx.h 658baf643644d47dea4e1e315da1b257e21822c3af6b00836e19962385c1d918
F examples/vstudio/wforms/AssemblyInfo.cpp 08e3cfc50233132ea5d4b70b47fa2bce669c2c6a97896f8b0ec62b882e1deeb1
F examples/vstudio/wforms/MainForm.h 4593f95e064b0b0701d5fd5e1852273e1a3bb40e62bf65b089e0ff434433f18f
F examples/vstudio/wforms/MainForm.resX f69089f338845d493eccdd05a2650a7f3cca9f0993f746723d7f7d08054d681f
F examples/vstudio/wforms/resource.h 3c4a478a4643ae9ccf7988df1613197a7f4ab3483455c8037004c6da26b036e9
F examples/vstudio/wforms/wforms.cpp 6566a4a77faae13ee3bdd474c347a62e68632c5f6b053194aa40d12689e4a160
F exrun 4450f57cd0ed563925652e0fc3af646a0fa471138831c1e120ec534aa65dd948 x
F exrun.bat e93b1f2be84a76a2c0addaeac179b94b92427c84a2392352d007ce55b66390b3 x
F install.hta.in c154df770e08f8b617f9aed85dbfe54e2650e64ab63f6afb791a3a00829ed678
F lib/Doxyfile.in af6c4130b34ba3981901654e81e6ec9b72312f4e6c140ebb0c1a2e467a0796e7
F lib/autoflag.h a59c91082888a869068a2ecaeb15187fd0ead8ea49dcc46c3602ecea6d13e1a5
F lib/beemutex.cpp 96fb5c8ce78eaad6f05bde1bc8f10b4ee49eb906bee8acb3cdae7947992027ca
F lib/beemutex.h e6e9f3dc7ee34ddb536660cb502a3d2f31c41870a02890b558e53f47ea8bfbf4
F lib/common.h 50319b5e32c88e83e8155e74d7fe9d54eb756f87579f33cbd9bf117e2ad7dab3
F lib/comparable.h a98c8235d2397cd9df10d0ea6f2c100bef5927311ab057859ce2b1edc635cd98
F lib/connection.cpp 8b3cd3cdc5368fa8f1f9618d54a5ae5194c77ced0f5054fd7105efebe5817c73
F lib/connection.h 2fefbf8fa991799abd2b05c693869434d0442b52053e09d9a0b17c8db4755141
F lib/cpool.cpp 5009c6f9cb53ad1b0266278ef99a36c851efba76d6aa8f0b5c8bacad59ed28f2
F lib/cpool.h 7c92f9c977f63edf4ae48b62c202744a9dbcf4b820fd3937ea4af2cd0f976aa6
F lib/custom.h c5c4fad1db5f5664b523ecbfc89e8070e36312978390e7022607a6e8f083e9c6
F lib/datetime.cpp 91c25d8bb20153f71b9fccc25e3fe8369dae1d47e44a930d7384e209d2cd844d
F lib/datetime.h 6909b15f4de43966990766538b8b803dcbc6fd6cccbacfe7d1723fdbf1ff1d17
F lib/dbdriver.cpp 060c01b92c0bf9372ad36c668bd3e0758f6f185b6910eb4c44d1248cec3115b9
F lib/dbdriver.h 1e55b72fed78c03a63bbcf25396f28a466b83039f0dcf050709baf4fa017f762
F lib/exceptions.h 9ba34d6b52adfc121541bc2eae090bb3049f4569796d149924e643b783e33cf9
F lib/field.h d91420ef9979651bb6d205843d1a1231a21ce9669e784f9692c7da06b721c215
F lib/field_names.cpp a862f4d46beac93d67232af39c5432be748890f60c96eff9e28b20afba431535
F lib/field_names.h 3844d72f4dc25d769b7633dd709bc10470b91efaa4a95eb9ab3d3a1b64ad580a
F lib/field_types.cpp 62358b473b37b30d701e6fd2eca9f9103a91747cc31c3e5a935e2ef58f0e069a
F lib/field_types.h f42e8d92974d7043b5f82e7c6f9772f0a05e61bfba7fa7761a2427c306beea18
F lib/manip.cpp 323cc3e6893d74c2b2d92d8df669f3e477f69cf1760748ed65b62e7b73986f12
F lib/manip.h d4b13821e990bab370ca33e4fa0f7d4423bcb854f718a1f1e3d554b24ca04330
F lib/myset.cpp 462c808158c304a45340a3bcb04bbfe25ecc36103ad2b88812f2efe7b1cd9f00
F lib/myset.h ef0e8187f92e527bc655ef52fc35fee1e22d664b14803a92575c5b2b8b9108a9
F lib/mysql++.cpp 4208335c42b3a92cf374da003176a971b25fc95654c8fa12c910ea9a2c281078
F lib/mysql++.h.in 30cf9f49c3452d029f7aae877a98f976567929f533376f60a4451527db3d6067
F lib/mystring.cpp e5a2fad8e872386bb7c2a54e0a5dd5276bcca0d3054d3cc521e11317d555eab1
F lib/mystring.h 6713e99d112fad53a454e6910214d8b4ec86cf305402cad13b01cd7ba6bc980d
F lib/noexceptions.h a83ca850360001f823b778cac4d7a4b13cbcfa0462d42eb607859890ff13e6d0
F lib/null.cpp aa270a63648c0177b322edab9abc3958b977708f00ca68104ae5caec4c3b448d
F lib/null.h 9e6b80c94692c7620b340563765c53502e3210f13d899e49383cef0fb7df9bd4
F lib/options.cpp 8324f394bc327d23d08052de1de65f90c10a91c2e78418275943aa9bd59266f1
F lib/options.h bae86268d87c0a21e4f86f33f7f4f962856e048d374cfb6131ea486ed58f3fab
F lib/qparms.cpp c3c7ece6a8cf4381813feb977ccd21cf076aec1af0b5056b0b2bbb12c1cfdb40
F lib/qparms.h 5c588181324ca7b04f8e450f22aa208420baf22d98cdb79939961ee7f69ad20f
F lib/query.cpp 1e2c1a8b9d0dcc34c0582e4ba31252baf9d58e9ef75e8625073779f2ad35df14
F lib/query.h 2494a3b70fc4742f48bcd68c778c01018c7f45c3289cf05f4894d8ad061ae352
F lib/querydef.h 36e1548019125e308893ead7f66fda6f8c4e6c63f22d23ed389084fa8fde7b79
F lib/querydef.pl 45aa58ad21f754645816ad4f467edd245ed7813fd368b1fe2a2c287943b9ea26 x
F lib/refcounted.h 998b1a0dd81ab643634780d0e3649aba9df8b871b258e0ca83e0788c7bd749b1
F lib/result.cpp 584fdf0423aabc16dd68ebef056d941b2a1a5a36c6e01079d55bdbf0c9012683
F lib/result.h c5369cb38cef6b78b24e0d89a7221c5e0c660731e93eae4dd314eecb7472f14c
F lib/row.cpp e63b58bf2b0b81a07682647f90bbcba9ba707c3b0061119c1f079a7cc2c359fb
F lib/row.h f960ffef4c8770896d0082e1848c7c809942ff765b760296e362641286e24fba
F lib/sql_buffer.cpp 47b7302a0544b6f909009f8a15709e60b8de296255c3f48f446100e0f7db53a0
F lib/sql_buffer.h e3b08b520773ea9522aef46915d257028ebd187b9e16d42959cba2e77193a036
F lib/sql_types.h 39e4f50db15f4bd90259d37c29536b99bcc05e53d737347c88f9d1ba4729bcda
F lib/ssqls.h 8383733878846610b82a15167eca58b351688fffb699bdf16d55e7dc4846a330
F lib/ssqls.pl b71f084a61ec04f872440b1cae49139d20794ab373ef5b550de9ede74837bc44 x
F lib/stadapter.cpp a442b9873af7db7a5fe706051504bba1db3ce63554493e46438f2ecd095c9a78
F lib/stadapter.h 03a0d046b893e3ebc764756f20f43b08e4e2ea547080da77a69deaeb24e416be
F lib/stream2string.h 954bb0596678efb62a008f0ef6da878f6a8ce7c75706c7d665c5fd948c024432
F lib/tcp_connection.cpp b63efa4be4d4bd595430be6b8cdf29aa98d9b19d6d675ad755a4fbc71c89a96c
F lib/tcp_connection.h ca96ef7b169003cdb260a8cbf01922b3f00e97db3dc52fb73c526f58a708691b
F lib/tiny_int.h a705514819ff29829b79b7c9cb8e3e23af477a0963bc74bb0e68f188824671e3
F lib/transaction.cpp d54556ce8dc8854edea437416e8d38b05ca2b5a9a0948c6b84632c1fddb28199
F lib/transaction.h 4c6f2e8d98c706f9f9eb7182fa044d2cef2a739c0c624d16f3d3508e00a39009
F lib/type_info.cpp 66596713e3ede7688225fdc43abe8a42dcc23c7d0f8c4741b58512e0332403f6
F lib/type_info.h 56062d1b2d6260109a76c9cbd69fffd7d9ba1d0e195f88fd4dd8a3adf4b09d67
F lib/uds_connection.cpp 7e5a2c5035877cc48f8410b26d0d0a042b7c232c6e7dfe0b4345d27cb3776e2e
F lib/uds_connection.h bbd2368909cc12c8dba7983695133970b5b16bd2288b672f1c9dcc1c2c589a06
F lib/vallist.cpp 9ea8d22a4e9c4326e5f5bd6e4dbbc9a5baa114cf4d197d46671fde3a3f945242
F lib/vallist.h 953c88603c2071499fe6483871df7d66a3bf5e55d79bb77383b0a08c0251b39b
F lib/wnp_connection.cpp 1e2516aa7b133e42421b1939acf9bbc0df9a5b1c2e1182e3e0169138d65497eb
F lib/wnp_connection.h 90fe41860cf9cd3f0dc34ec1ca60ea0bb88450e866292c59518aa1c9636eacb4
F libmysqlclient.def 02e8547aed2a92862e8b2f498f9808ec59bc407603c0d547ffdeedd74a49a153
F mysql++.bkl 3e2846f66404164fd0116dce3ced80249c5633022d03296b6d84ea3317723583
F mysql++.ebuild de1fcd8a8596bfe5d661f280c333d3db202482c181ad0e3660fd6948e430ff6e
F mysql++.spec.in 1bed63a95fbcbfde8e2510c6771768cf171eb3d04c2552c3cda2f1e52ea7c300
F osver 034cabb5f0517c3b0a3bedcf712289fd6b4b205ee9576940a1440dc85060c230 x
F pretty.pl 011358a7e49ceab10b1bcd5e8484edd2b28e3874723ffa95677b79f74ae7e010 l
F rebake.bat edb44b9acedd5fb9008b2f66a96f3e5dc525128384487a6ce52e9c5fbc19408f
F shared-ld-sh 4a4b7d62c5932759ee791d66e52752413fa601f4200ea464798320606e59b5a8 x
F test/cpool.cpp fa5271d45eb5fe5ae26d0633d3d38bbd6d1876a1b5a20a6bab62a1a254ef62c1
F test/datetime.cpp 99baffdc833b131f3558463b051f6c18f7f6a043dff5b78ae2103bf6b94440ea
F test/inttypes.cpp 29636e8859048edd599852a0282dd6f097b445595321e5f8ad0e07700894d3fe
F test/manip.cpp 52214e0998614544a5de08a9a6deb999d1e404808b1e854f55d48a235006e896
F test/null_comparison.cpp e26bda6ffe9f0488c225590b7646c357fa0f5449479ab944b1b6b0ec3cc44759
F test/null_uniqueness.cpp 8691dd4fa5d72ed468cd542204b9ad1ded566f414194000837022785e02fa215
F test/qssqls.cpp d7b94f5460e892e32511095a7618d7752ed09e3d0ed7a7eaea95715465fa7038
F test/qstream.cpp 5b45a5599c80dceae64eaffbebb0ecd89043518869e105eff45a9977d0fbf684
F test/string.cpp b8e962af63c80864c3d3fd658c3fe38314d353ea3c2ededb719d4fa92fcac3ab
F test/tcp.cpp 087ebd40fc7880bc950e089c0cb78da4d00081d9168040c4b418568438e45a26
F test/uds.cpp 0e0c9705f91da41b6bc03fc9a2e7af6ca322d28d055a37eb6c4af929489a967f
F test/wnp.cpp 8f784f015f436b6cbd0d15e93c218b704df484605bf31553e30fd5e6939f1813
P cfc10208deaa0af3573376e21e6c9b1f6d3f0b48f908762d2e65aa87871253de
R 168d523428cbfd2740b8e180c0138faf
T +sym-v3.0.6 *
U tangent
Z 459c40537c73ffee45c11e148edba735

Changes to ssx/genv2.cpp.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
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
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
/***********************************************************************
 ssx/genv2.cpp - Walks the SSQLS v2 parse result, writing back out
 	the equivalent SSQLS v2 DSL code.  This is useful for testing that
	our parser has correctly understood a given piece of code.  It is
	also something like the preprocessor mode of a C++ compiler,
	emitting a digested version of its input.

 Copyright (c) 2009 by Warren Young and (c) 2009-2010 by Educational
 Technology Resources, Inc.  Others may also hold copyrights on code
 in this file.  See the CREDITS.txt file in the top directory of the
 distribution for details.

 This file is part of MySQL++.

 MySQL++ is free software; you can redistribute it and/or modify it
 under the terms of the GNU Lesser General Public License as published
 by the Free Software Foundation; either version 2.1 of the License, or
 (at your option) any later version.

 MySQL++ is distributed in the hope that it will be useful, but WITHOUT
 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
 License for more details.

 You should have received a copy of the GNU Lesser General Public
 License along with MySQL++; if not, write to the Free Software
 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
 USA
***********************************************************************/

#include "genv2.h"

#include "parsev2.h"

#include <cstring>
#include <iostream>
#include <fstream>
#include <typeinfo>

using namespace std;

//// generate_ssqls2 ///////////////////////////////////////////////////
// 2 versions: second checks its arguments and opens the named file,
// calling the second to actually generate the SSQLS v2 output from
// the parse result only if we were given sane parameters.

static bool
generate_ssqls2(ostream& os, const ParseV2* pparse)
{
	ParseV2::LineListIt it;
	for (it = pparse->begin(); it != pparse->end(); ++it) {
		if (dynamic_cast<ParseV2::Field*>(*it)) {
			// 'field' directives must be indented under the preceding
			// 'table'.  We don't want to hard-code this in
			// ParseV2::Field::print() in case we later start calling
			// those routines for other reasons, such as to construct
			// error messages.  It's really a special case of -o, not
			// really something that print() routine should know.
			os << '\t';
		}
		os << **it << endl;
	}

	return true;
}

bool
generate_ssqls2(const char* file_name, const ParseV2* pparse)
{
	if (pparse) {
		if (strcmp(file_name, "-") == 0) {
			return generate_ssqls2(cout, pparse);
		}
		else {
			ofstream ofs(file_name);
			if (ofs) {
				cout << "TRACE: Generating SSQLS v2 file " << file_name <<
						" from " << (pparse->end() - pparse->begin()) <<
						" line parse result." << endl;
				return generate_ssqls2(ofs, pparse);
			}
			else {
				cerr << "Failed to open " << file_name << \
						" for writing for -o!" << endl;
				return false;
			}
		}
	}
	else {
		cerr << "No parse result given to -o handler!" << endl;
		return false;
	}
}
<
<
<
<
<
<
|
<
<
<
<
|
<
|
<
<
<
<
|
<
<
<
<
|
<
<
<
<
<
|
<

<
|
<
<
<
<

<
|
<
<
<
<
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<






1




2

3




4




5





6

7

8




9

10




11





















































SHELL := $(COMSPEC)




MYSQL_DIR := "c:/Program Files/MySQL/MySQL Connector C 6.1"

CXXFLAGS := -I$(MYSQL_DIR)/include -Ic:/MySQL++/include




LDFLAGS := -L$(MYSQL_DIR)/lib/opt -Lc:/MySQL++/lib/MinGW




LDLIBS := -lmysqlclient -lmysqlpp





EXECUTABLE := hello



all: $(EXECUTABLE)






clean: 




	del $(EXECUTABLE)















































Changes to ssx/genv2.h.

1

2


3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33

/***********************************************************************

 ssx/genv2.h - Mechanism for generating SSQLS v2 DSL code from


 	an SSQLS v2 parse result.  Implements ssqlsxlat -o flag.

 Copyright (c) 2009 by Warren Young.  Others may also hold copyrights
 on code in this file.  See the CREDITS.txt file in the top directory
 of the distribution for details.

 This file is part of MySQL++.

 MySQL++ is free software; you can redistribute it and/or modify it
 under the terms of the GNU Lesser General Public License as published
 by the Free Software Foundation; either version 2.1 of the License, or
 (at your option) any later version.

 MySQL++ is distributed in the hope that it will be useful, but WITHOUT
 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
 License for more details.

 You should have received a copy of the GNU Lesser General Public
 License along with MySQL++; if not, write to the Free Software
 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
 USA
***********************************************************************/

#if !defined(MYSQLPP_SSX_GENV2_H)
#define MYSQLPP_SSX_GENV2_H

class ParseV2;
extern bool generate_ssqls2(const char* file_name, const ParseV2* pparse);

#endif // !defined(MYSQLPP_SSX_GENV2_H)

<
>
|
>
>
|
|
<
<
|
|
|

<
<
<
<
|
<
<
<
<
|
<
<
<
<
<
|
<
<

|
<
|
<
>

1
2
3
4
5
6


7
8
9
10




11




12





13


14
15

16

17

<!ELEMENT xi:include (xi:fallback?) >
<!ATTLIST xi:include
    xmlns:xi   CDATA       #FIXED    "http://www.w3.org/2001/XInclude"
    href       CDATA       #IMPLIED
    parse      (xml|text)  "xml"
    xpointer   CDATA       #IMPLIED


    encoding   CDATA       #IMPLIED 
    accept     CDATA       #IMPLIED
    accept-language CDATA  #IMPLIED >





<!ELEMENT xi:fallback ANY>




<!ATTLIST xi:fallback





    xmlns:xi   CDATA   #FIXED   "http://www.w3.org/2001/XInclude" >



<!ENTITY % local.chapter.class "| xi:include">

<!ENTITY % local.divcomponent.mix "| xi:include">

<!ENTITY % local.para.char.mix "| xi:include">

Changes to ssx/main.cpp.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
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
56
57
58
59
60
61
62
63

64
65
66


67
68
69
70
71
72
73
74
75
76
77

78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114


115
116
117
118
119
120


121
122
123
124
125
126
127
128
129
130
131
132
/***********************************************************************
 ssx/main.cpp - Main driver module for ssqlsxlat, which does several
 	data translations related to the SSQLSv2 mechanism of MySQL++.  The
	primary one is SSQLSv2 language files (*.ssqls) to C++ source code,
	but there are others.  Run "ssqlsxlat -?" to get a complete list.

 Copyright (c) 2009 by Warren Young and (c) 2009-2010 by Educational
 Technology Resources, Inc.  Others may also hold copyrights on code
 in this file.  See the CREDITS.txt file in the top directory of the
 distribution for details.

 This file is part of MySQL++.

 MySQL++ is free software; you can redistribute it and/or modify it
 under the terms of the GNU Lesser General Public License as published
 by the Free Software Foundation; either version 2.1 of the License, or
 (at your option) any later version.

 MySQL++ is distributed in the hope that it will be useful, but WITHOUT
 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
 License for more details.

 You should have received a copy of the GNU Lesser General Public
 License along with MySQL++; if not, write to the Free Software
 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
 USA
***********************************************************************/

#include "genv2.h"
#include "parsev2.h"

#include <cmdline.h>

#include <iostream>

using namespace std;
using namespace mysqlpp::ssqlsxlat;


//// parse_ssqls2 //////////////////////////////////////////////////////
// We were given the name of a putative SSQLS v2 source file; try to
// parse it.

static ParseV2*
parse_ssqls2(const char* file_name)
{
	try {
		cout << "Parsing SSQLS v2 file " << file_name << "..." << endl;
		ParseV2* pt = new ParseV2(file_name);
		cout << file_name << " parsed successfully, " <<
				(pt->end() - pt->begin()) << " interesting lines." <<
				endl;
		return pt;
	}
	catch (const ParseV2::FileException& e) {
		cerr << file_name << ":0" << 
				": file I/O error in SSQLS v2 parse: " <<
				e.what() << endl;
	}
	catch (const ParseV2::ParseException& e) {
		cerr << e.file_name() << ':' << e.line() << ':' <<
				e.what() << endl;

	}
	catch (const std::exception& e) {
		cerr << file_name << ":0" << 


				": critical error in SSQLS v2 parse: " <<
				e.what() << endl;
	}
	return 0;
}


//// main //////////////////////////////////////////////////////////////

int
main(int argc, char* argv[])

{
	// Parse the command line
	CommandLine cmdline(argc, argv);
	if (cmdline) {
		ParseV2* ptree = 0;

		switch (cmdline.input_source()) {
			case CommandLine::ss_ssqls2:
				ptree = parse_ssqls2(cmdline.input());
				break;

			default:
				cerr << "Sorry, I don't yet know what to do with input "
						"source type " << int(cmdline.input_source()) <<
						'!' << endl;
				return 2;
		}

		if (cmdline.output_sink() != CommandLine::ss_unknown) {
			if (ptree) {
				switch (cmdline.output_sink()) {
					case CommandLine::ss_ssqls2:
						if (generate_ssqls2(cmdline.output(), ptree)) {
							return 0;
						}
						else {
							return 2;
						}

					default:
						cerr << "Sorry, I don't yet know what to do "
								"with sink type " <<
								int(cmdline.output_sink()) << '!' <<
								endl;
						return 2;
				}
			}


			else {
				// Depending on someone farther up the line to write
				// the error message, explaining why we didn't get a
				// parse tree.
				return 2;
			}	


		}
		else {
			cerr << "Sorry, I don't know how to write C++ output yet." <<
					endl;
			return 2;
		}
	}
	else {
		return 1;
	}
}

<
<
<
<
<
|
<
<
<
<

<
|
<
<
<
<
|
<
<
<
<
|
<
<
<
<
<
|
<
<
|
<

<
|
<
<

|
<
<
<
|
<
<
<
<
<
<
<
<
<
<
<
<
<
|
<
|
<
<
<
>
|
<
<
>
>
<
<
|
<
<
|
|
<
|
<
<
>
|
<
<
<
<
|
<
<
<
<
|
<
<
<
<
<
|
|
<
<
<
<
<
<
|
<
<
<
|
<
|
<
<
<
<
|
<
>
>
|
<
<
<
<
|
>
>
|
<
<
<
<
<
<
<
<
<
<
|





1




2

3




4




5





6


7

8

9


10
11



12













13

14



15
16


17
18


19


20
21

22


23
24




25




26





27
28






29



30

31




32

33
34
35




36
37
38
39










40





- Change version number in configure.ac and mysql++.bkl.






  All other places the version number occurs are generated files




  created from one of these two.  If there's a corresponding *.in file




  for the one you're looking at, the version number was substituted in





  by autoconf from configure.ac.  Otherwise, the file was most likely


  created by the build system using the version number in mysql++.bkl.



- Run "make abicheck".  There should be no changes.



  You may have to run the following command in the current "stable"



  directory before this will succeed, since it depends on there being













  an ACC dump file in place already.





      $ abi-compliance-checker -lib mysqlpp -dump abi.xml



  ("Stable" is assumed to be in ../3.1.0 relative to the svn "head"
  checkout, as I write this.)





  This dependence on an existing ABI dump file is deemed reasonable
  since the ABI of the stable version had better not be changing!

  Plus, it saves some processing time, since ACC can load the stable


  ABI info without re-parsing its headers and library file.





- Re-bootstrap the system in pedantic mode, then do a clean rebuild.




  Fix any new errors and warnings.






  Known bogus warnings:










  - Query's std::basic_ios<> base class is not being initialized.

    Yes, we know.  We don't care.






  - The "==" float comparisons in lib/stadapter.cpp are harmless.
    They're comparisons against special NaN and infinity constants.
    Those are safe.





- Re-bootstrap it again without "pedantic", to avoid shipping the
  pedantic build files.











- make rpm on each CentOS version we currently support.

Changes to ssx/parsev2.cpp.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
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
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
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
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
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
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
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
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
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
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
/***********************************************************************
 ssx/parsev2.cpp - Parser for the SSQLS v2 language.

 Copyright (c) 2009 by Warren Young.  Others may also hold copyrights
 on code in this file.  See the CREDITS.txt file in the top directory
 of the distribution for details.

 This file is part of MySQL++.

 MySQL++ is free software; you can redistribute it and/or modify it
 under the terms of the GNU Lesser General Public License as published
 by the Free Software Foundation; either version 2.1 of the License, or
 (at your option) any later version.

 MySQL++ is distributed in the hope that it will be useful, but WITHOUT
 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
 License for more details.

 You should have received a copy of the GNU Lesser General Public
 License along with MySQL++; if not, write to the Free Software
 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
 USA
***********************************************************************/

#include "parsev2.h"

#include <utility.h>

#include <algorithm>
#include <cassert>
#include <cctype>
#include <cerrno>
#include <cstring>
#include <iostream>

using namespace std;

// System error value to string conversion
#if defined(MYSQLPP_PLATFORM_WINDOWS)
#	define SYSERR ""
#else
#	define SYSERR ": " << strerror(errno)
#endif

////////////////////////////////////////////////////////////////////////
// Instantiate static members

ParseV2::StringList ParseV2::File::search_path_;


ParseV2::ParseV2(const char* file_name) :
file_(file_name)
{
	// For each line in the file, read it in and try to make sense of it
	// based on the indent level and the leading verb.
	//cout << "TRACE: parsing SSQLS v2 file " << file_name << '.' << endl;
	string line;
	bool subdirective;
	while (file_.read_line(line, subdirective)) {
		// Skip empty lines
		if (line.empty()) continue;

		// Break line up into whitespace-separated tokens
		StringList tokens;
		tokenize(tokens, line);
		if (tokens.empty()) continue;		// shouldn't happen

		// Try to interpret token list
		Line* line = Line::parse(tokens, subdirective, file_);
		assert(line != 0);	// errors should be signalled with exceptions
		Include* iline = dynamic_cast<Include*>(line);
		if (iline) {
			// Include lines are a special case: we hoist the parsed
			// lines from the included file up into our line list.
			lines_.reserve(lines_.size() + (iline->end() - iline->begin()));
			for (LineListIt it = iline->begin(); it != iline->end(); ++it) {
				lines_.push_back(*it);
			}
			delete iline;
		}
		else {
			// Normal case: add line to our line list
			lines_.push_back(line);
		}
	}
}


void
ParseV2::tokenize(StringList& tokens, const std::string& line) const
{
	// Skip over leading whitespace
	string::const_iterator current = line.begin();
	while (current != line.end() && isspace(*current)) {
		++current;
	}

	// Break rest of line up into space-separated words, treating
	// consecutive spaces as single separators, and ignoring trailing
	// spaces.
	while (current != line.end()) {
		string::const_iterator word_start = current;
		while (current != line.end() && !isspace(*current)) ++current;
		tokens.push_back(string(word_start, current));
		while (current != line.end() && isspace(*current)) ++current;
	}
#if 0
	cout << "TRACE: " << tokens.size() << " tokens in line '" << line <<
			"':" << endl;
	cout << "\t";
	for (StringListIt it = tokens.begin(); it != tokens.end(); /* */) {
		cout << '\'' << *it++ << '\'';
		if (it != tokens.end()) cout << ',';
	}
	cout << endl;
#endif
}


void
ParseV2::AccessorStyleOption::print(std::ostream& os) const
{
	os << "option accessor_style ";
	switch (type_) {
		case camel_case_lower:	os << "getX"; break;
		case camel_case_upper:	os << "GetX"; break;
		case overloaded:		os << "x"; break;
		case stroustrup:		os << "get_x"; break;
		case unknown:			os << "UNKNOWN"; break;
	}
}


ParseV2::AccessorStyleOption::Type
ParseV2::AccessorStyleOption::parse_type(const std::string& style,
		const File& file)
{
	//cout << "TRACE: found accessor style " << style << endl;
	if (style.compare("getX") == 0) {
		return camel_case_lower;
	}
	else if (style.compare("GetX") == 0) {
		return camel_case_upper;
	}
	else if (style.compare("get_x") == 0) {
		return stroustrup;
	}
	else if (style.compare("x") == 0) {
		return overloaded;
	}
	else {
		ostringstream o;
		o << "unknown accessor style '" << style << '\'';
		file.parse_error(o);
		return unknown;
	}
}


void
ParseV2::ExceptionOnSchemaMismatchOption::print(std::ostream& os) const
{
	os << "option exception_on_schema_mismatch " <<
			(throw_ ? "true" : "false");
}


ParseV2::Field*
ParseV2::Field::parse(const StringList& tl, bool subdirective,
		const File& file)
{
	// Check for obviously wrong inputs
	if (tl.size() < 2) {
		file.parse_error("'field' directive requires at least one argument");
	}
	else if (!subdirective) {
		file.parse_error("'field' must be a subdirective");
	}

	// Get field name
	StringListIt it = ++tl.begin();	// skip over 'field'
	string name(*it++);
	//cout << "TRACE: found field " << name << endl;

	// Scan rest of token list, interpreting the name/value pairs.
	string type, alias;
	bool is_autoinc = false, is_key = false, is_null = false,
			is_unsigned = false;
	while (tl.end() - it > 1) {
		string attr(*it++), value(*it++);
		mysqlpp::internal::str_to_lwr(attr);
		if (attr.compare("alias") == 0) {
			alias = value;
		}
		else if (attr.compare("is") == 0) {
			if (value.compare("autoinc") == 0) {
				is_autoinc = true;
			}
			else if (value.compare("key") == 0) {
				is_key = true;
			}
			else if (value.compare("null") == 0) {
				is_null = true;
			}
			else if (value.compare("unsigned") == 0) {
				is_unsigned = true;
			}
			else {
				ostringstream o;
				o << "unknown is-attribute '" << value << 
						"' for field '" << name << '\'';
				file.parse_error(o);
			}
		}
		else if (attr.compare("type") == 0) {
			type = value;
		}
		else {
			ostringstream o;
			o << "bad attribute '" << attr << "' for field " << name;
			file.parse_error(o);
		}
	}

	// Warn if field wasn't given an explicit type
	if (type.empty()) {
		cerr << "Warning: field '" << name << "' defaulting to "
				"string type." << endl;
	}

	// No attribute errors, so create the Field object.  
	return new Field(name, type, is_unsigned, is_null, is_autoinc,
			is_key, alias);
}


void
ParseV2::Field::print(std::ostream& os) const
{
	os << "field " << name_ << ' ';
	type_.print(os);
	if (is_autoinc_)	os << " is autoinc";
	if (is_key_)		os << " is key";
	if (is_null_)		os << " is null";
	if (is_unsigned_)	os << " is unsigned";
	if (alias_.size())	os << " alias " << alias_;
}


ParseV2::Field::Type::Type(const std::string& s) :
value_(ft_string)
{
	// Force s to lowercase as ls, for easier comparisons below
	string ls(s);
	mysqlpp::internal::str_to_lwr(ls);
	//cout << "TRACE: field type " << s << endl;

	// Suss out appropriate field type in piecewise fashion.  This
	// parser isn't terribly robust, but it should do sane things in the
	// presence of plausible input.  Feed it garbage, and the worst that
	// will happen is that it will either give up, letting the default
	// of ft_string stand, or it may happen to recognize some substring
	// in the input that causes it to assign some other type.
	if ((ls.find("blob") != string::npos) ||
			(ls.find("varbinary") != string::npos)) {
		value_ = ft_blob;
	}
	else if (ls.find("bool") == 0) {
		value_ = ft_tinyint;
	}
	else if (ls.find("date") == 0) {
		if (ls.compare("datetime") == 0) value_ = ft_datetime;
		else value_ = ft_date;
	}
	else if ((ls.find("decimal") != string::npos) ||
			(ls.find("double") != string::npos) ||
			(ls.find("fixed") != string::npos) ||
			(ls.find("numeric") != string::npos)) {
		value_ = ft_double;
	}
	else if (ls.find("float") != string::npos) {
		value_ = ft_float;
	}
	else if (ls.find("int") != string::npos) {
		if (ls.find("tiny") == 0) value_ = ft_tinyint;
		else if (ls.compare("int1") == 0) value_ = ft_tinyint;
		else if (ls.find("small") == 0) value_ = ft_smallint;
		else if (ls.compare("int2") == 0) value_ = ft_smallint;
		else if (ls.find("big") == 0) value_ = ft_bigint;
		else if (ls.compare("int8") == 0) value_ = ft_bigint;
		else value_ = ft_mediumint;
	}
	else if (ls.find("set") != string::npos) {
		value_ = ft_set;
	}
	else if (ls.find("time") == 0) {
		if (ls.compare("timestamp") == 0) value_ = ft_datetime;
		else value_ = ft_time;
	}
}


void
ParseV2::Field::Type::print(std::ostream& os) const
{
	os << "type ";
	switch (value_) {
		case ft_bigint:		os << "bigint";		break;
		case ft_blob:		os << "blob";		break;
		case ft_date:		os << "date";		break;
		case ft_datetime:	os << "datetime";	break;
		case ft_double:		os << "double";		break;
		case ft_float:		os << "float";		break;
		case ft_mediumint:	os << "mediumint";	break;
		case ft_set:		os << "set";		break;
		case ft_smallint:	os << "smallint";	break;
		case ft_string:		os << "string";		break;
		case ft_time:		os << "time";		break;
		case ft_tinyint:	os << "tinyint";	break;
	}
}


ParseV2::File::File(const char* file_name) :
file_name_(file_name),
line_number_(1)
{
	// Try to open the named file for reading
	//cout << "TRACE: opening file " << file_name << endl;
	StringListIt it = search_path_.begin();
	string path(file_name_);
	while (true) {
		ifs_.open(path.c_str());
		if (ifs_) {
			// Opened it, so add directory part of file path (if any) to
			// our search path.
			add_directory_to_search_path(file_name);
			break;
		}
		else if (it == search_path_.end()) {
			// Ran out of things to try
			ostringstream o;
			o << "Failed to open '" << file_name_ << "' for reading" <<
					SYSERR;
			error(o);
		}
		else {
			// Replace previous path with the next possibility, which
			// we'll try on the next iteration.
			path = *it++;
			path += MYSQLPP_PATH_SEPARATOR;
			path += file_name_;
		}
	}
}


void
ParseV2::File::add_directory_to_search_path(const char* filepath)
{
	//cout << "TRACE: adding directory part of " << filepath << 
	//		" to search path." << endl;
	StringList parts;
	split_path(parts, filepath);
	if (parts.size() > 1) {
		// There's a path part, so check that it's not just '.', the
		// current directory on all the systems we're portable to.
		if (parts.size() != 2 || parts[0].compare(".") != 0) {
			// Path is interesting, so reassemble the directory part
			string path(parts[0]);
			StringListIt it = ++parts.begin();
			while (it < parts.end() - 1) {	// ignore last part; file name
				path += MYSQLPP_PATH_SEPARATOR;
				path += *it++;
			}

			// Add that directory to the search path unless it's already
			// in the list.
			if (find(search_path_.begin(), search_path_.end(), path) ==
					search_path_.end()) {
				search_path_.push_back(path);
				//cout << "TRACE: added new directory " << path << 
				//		" to search path." << endl;
			}
		}
	}
}


void
ParseV2::File::error(const std::string& msg) const
{
	throw FileException(msg);
}


void
ParseV2::File::parse_error(const std::string& msg) const
{
	throw ParseException(msg, file_name_, line_number_);
}


bool
ParseV2::File::read_line(std::string& line, bool& subdirective)
{
	line.clear();
	if (ifs_) {
		static char temp[100];
		ifs_.getline(temp, sizeof(temp));
		if (ifs_) {
			++line_number_;
			line = temp;
			size_t n = line.find('#');
			if (n != string::npos) {
				line.resize(n);
			}
			if (line.size()) {
				subdirective = isspace(line[0]);
			}
			return true;
		}
	}
	return false;
}


void
ParseV2::File::split_path(StringList& parts, const std::string& path) const
{
	//cout << "TRACE: splitting path '" << path << "'..." << endl;
	const char sep = MYSQLPP_PATH_SEPARATOR;
	for (string::const_iterator it = path.begin(); it < path.end(); /* */) {
		string::const_iterator part_start = it;
		while (it != path.end() && (*it != sep)) ++it;
		parts.push_back(string(part_start, it));
		while (it != path.end() && (*it == sep)) ++it;
	}
#if 0
	cout << "TRACE: " << parts.size() << " parts in path '" << path << "': ";
	for (StringListIt it = parts.begin(); it != parts.end(); /* */) {
		cout << *it++;
		if (it != parts.end()) cout << sep;
	}
	cout << endl;
#endif
}


void
ParseV2::HeaderExtensionOption::print(std::ostream& os) const
{
	os << "option header_extension " << value();
}


void
ParseV2::ImplementationExtensionOption::print(std::ostream& os) const
{
	os << "option implementation_extension " << value();
}


ParseV2::Include*
ParseV2::Include::parse(const StringList& tl, bool subdirective,
		const File& file)
{
	// Check for obviously wrong inputs
	if (tl.size() != 2) {
		file.parse_error("'include' directive requires one argument");
	}
	else if (subdirective) {
		file.parse_error("'include' cannot be a subdirective");
	}

	// Above ensures that there is only one argument, so create Include
	// object from it, assuming it's a file name.
	//cout << "TRACE: including " << tl[0] << "..." << endl;
	return new Include((++tl.begin())->c_str());
}


ParseV2::Line*
ParseV2::Line::parse(const StringList& tl, bool subdirective,
		const File& file)
{
	// True if the last top-level directive we saw was 'table'
	static bool last_tld_was_table = false;

	// Pull the directive off the front of the list
	assert(!tl.empty());
	string directive(tl[0]);

	// First, recognize directives that expect subdirectives.
	mysqlpp::internal::str_to_lwr(directive);
	//cout << "TRACE: found " << directive << " line." << endl;
	if (directive.compare("table") == 0) {
		if (!subdirective) last_tld_was_table = true;
		return ParseV2::Table::parse(tl, subdirective, file);
	}
	else {
		// Next recognize directives that either stand alone at the top
		// level, or are always subdirectives.
		if (!subdirective) {
			last_tld_was_table = false;
		}

		if (directive.compare("field") == 0) {
			if (last_tld_was_table) {
				return ParseV2::Field::parse(tl, subdirective, file);
			}
			else {
				file.parse_error("'field' directive must follow 'table'");
			}
		}
		else if (directive.compare("include") == 0) {
			return ParseV2::Include::parse(tl, subdirective, file);
		}
		else if (directive.compare("option") == 0) {
			return ParseV2::Option::parse(tl, subdirective, file);
		}
	}

	// None of the code above recognized the directive.  Yell about it
	// with an exception.  Return doesn't actually happen, it just
	// squishes a compiler warning.
	ostringstream o;
	o << "unrecognized directive '" << directive << '\'';
	file.parse_error(o);
	return 0;
}


ParseV2::Option*
ParseV2::Option::parse(const StringList& tl, bool subdirective,
		const File& file)
{
	// Check for obviously wrong inputs
	if (tl.size() != 3) {
		file.parse_error("'option' directive requires two arguments");
	}
	else if (subdirective) {
		file.parse_error("'option' cannot be a subdirective");
	}

	// See if we can make sense of the first argument, which should be
	// the option name.
	string name(tl[1]);
	string value(tl[2]);
	//cout << "TRACE: found " << name << " = '" << value <<
	//		"' option." << endl;
	if (name.compare("accessor_style") == 0) {
		return new AccessorStyleOption(value, file);
	}
	else if (name.compare("exception_on_schema_mismatch") == 0) {
		return new ExceptionOnSchemaMismatchOption(value);
	}
	else if (name.compare("header_extension") == 0) {
		return new HeaderExtensionOption(value);
	}
	else if (name.compare("implementation_extension") == 0) {
		return new ImplementationExtensionOption(value);
	}
	else {
		ostringstream o;
		o << "unknown option '" << name << '\'';
		file.parse_error(o);
		return 0;
	}
}


bool
ParseV2::Option::parse_bool(const std::string& value)
{
	// Lowercase the given string for easier comparison
	string b(value);
	mysqlpp::internal::str_to_lwr(b);
	
	// Recognize only known falsy values, as SSQLS v2 options all
	// default to false, so the assumption is that any option that's
	// set at all is almost certainly to flip it from its default, to
	// true.  So, only definite false values are actually critical to
	// recognize, that being the surprising case.
	return !(
			b.compare("0") == 0 ||
			b.compare("false") == 0 ||
			b.compare("no") == 0 ||
			b.compare("off") == 0
		);
}


ParseV2::Table::Table(const std::string& name, const std::string& alias,
		const std::string& filebase) :
name_(name),
alias_(alias.empty() ? name : alias),
filebase_(filebase.empty() ? name : filebase)
{
}


ParseV2::Table*
ParseV2::Table::parse(const StringList& tl, bool subdirective,
		const File& file)
{
	// Check for obviously wrong inputs
	if (tl.size() < 2) {
		file.parse_error("'table' directive requires at least one argument");
	}
	else if (subdirective) {
		file.parse_error("'table' cannot be a subdirective");
	}

	// Get table name
	StringListIt it = ++tl.begin();	// skip over 'table'
	string name(*it++);
	//cout << "TRACE: found '" << name << "' table." << endl;

	// Scan rest of token list, interpreting the name/value pairs.
	string alias, filebase;
	while (tl.end() - it > 1) {
		string attr(*it++), value(*it++);
		mysqlpp::internal::str_to_lwr(attr);
		if (attr.compare("alias") == 0) {
			alias = value;
		}
		else if (attr.compare("filebase") == 0) {
			filebase = value;
		}
		else {
			ostringstream o;
			o << "bad attribute '" << attr << "' for table " << name;
			file.parse_error(o);
		}
	}

	// No attribute errors, so create the Table object.  
	return new Table(name, alias, filebase);
}


void
ParseV2::Table::print(std::ostream& os) const
{
	os << "table " << name_;
	if (alias_.size())		os << " alias " << alias_;
	if (filebase_.size())	os << " filebase " << filebase_;
}


ostream&
operator<<(ostream& os, const ParseV2::Line& line)
{
	line.print(os);
	return os;
}

<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
|
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<




































































































































































































































































































































































1
2

















































































































































































































































































































































































































































































































































































































































































#!/bin/sh
echo @MYSQLPP_VERSION_MAJOR@.@MYSQLPP_VERSION_MINOR@.@MYSQLPP_VERSION_BUGFIX@













































































































































































































































































































Changes to ssx/parsev2.h.

1

2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
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
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79

80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
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
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
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205


206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
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
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
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
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
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401

402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441

442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482

483
484
485

486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562


563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
/***********************************************************************

 ssx/parsev2.h - Declares the SSQLS v2 language parsing related classes.

 Copyright (c) 2009 by Warren Young and (c) 2009-2010 by Educational
 Technology Resources, Inc.  Others may also hold copyrights on code
 in this file.  See the CREDITS.txt file in the top directory of the
 distribution for details.

 This file is part of MySQL++.

 MySQL++ is free software; you can redistribute it and/or modify it
 under the terms of the GNU Lesser General Public License as published
 by the Free Software Foundation; either version 2.1 of the License, or
 (at your option) any later version.

 MySQL++ is distributed in the hope that it will be useful, but WITHOUT
 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
 License for more details.

 You should have received a copy of the GNU Lesser General Public
 License along with MySQL++; if not, write to the Free Software
 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
 USA
***********************************************************************/

#if !defined(MYSQLPP_SSX_PARSEV2_H)
#define MYSQLPP_SSX_PARSEV2_H

#include <exceptions.h>

#include <cassert>
#include <fstream>
#include <string>
#include <vector>

/// \brief Parses SSQLS v2 documents and holds the parse result
///
/// Construct an object of this type from a file name, and you will
/// get either a parse result or a thrown exception.
class ParseV2
{

public:
	/// \brief List of tokens as returned by boost::algorithm::split
	typedef std::vector<std::string> StringList;

	/// \brief Iterator into a StringList
	///
	/// This is const because StringLists are never modified once created
	typedef StringList::const_iterator StringListIt;

	/// \brief Holds information about an SSQLS v2 file we're parsing
	///
	/// This class exists simply because there's so much file-related
	/// processing in the parser, and it's confusing to have it
	/// scattered about.
	class File
	{
	public:
		/// \brief Open a file for reading, using the search path to
		/// file the file if the direct path isn't readable.
		File(const char* file_name);

		/// \brief Throw a FileException containing the given message
		void error(const std::string& msg) const;

		/// \sa error(const std::string&)
		void error(const std::ostringstream& msg) const
				{ error(msg.str()); }

		/// \brief Return the file's name
		const char* name() const { return file_name_.c_str(); }

		/// \brief Throw a ParseException containing the given message
		/// and our stored info about the file name and current line
		void parse_error(const std::string& msg) const;

		/// \sa parse_error(const std::string&)
		void parse_error(const std::ostringstream& msg) const

				{ error(msg.str()); }

		/// \brief Read a line in from a file
		///
		/// We read the line from our internal file object, trimming any
		/// trailing comment.  Does \e not trim whitespace; we depend on
		/// ParseV2::tokenize() to cope with that.  Sets subdirective
		/// flag if we see leading whitespace before we trim it away, as
		/// indented lines are interpreted differently by File's users.
		///
		/// \return false if our internal file object is in an error
		/// condition on entering or exiting this function.
		bool read_line(std::string& line, bool& subdirective);

	private:
		/// \brief Given the path to a file that is known to exist,
		/// extract the directory part (if any) and apppend it to our
		/// file search path.
		///
		/// This allows 'include' directives to find other files in the
		/// same directory as the included file when the first inclusion
		/// refers to a file not in the current directory.  Because the
		/// search path is static, it doesn't matter who "learns" about
		/// a useful directory.  Every file open from there on benefits.
		void add_directory_to_search_path(const char* filepath);

		/// \brief Break a file path up into a series of elements by the
		/// platform's directory separator, dropping '.' elements.
		void split_path(StringList& parts, const std::string& path) const;

		/// \brief File we're reading from
		std::ifstream ifs_;

		/// \brief Name of we're parsing
		///
		/// Used to construct useful error messages
		std::string file_name_;

		/// \brief Line number in file we're parsing
		///
		/// Used to construct useful error messages
		size_t line_number_;

		/// \brief Directories used in searching for included files
		///
		/// This is a \c vector, rather than a \c set, because order
		/// matters.  We grow this list as we go deeper into an inclusion
		/// tree, with the earlier paths taking precedence.
		///
		/// It's static because we only need on search path, and want
		/// new additions to inform all future parses in this session.
		static StringList search_path_;
	};

	//// Types of parsed lines, and related stuff
	/// \brief Base class for parsed SSQLS v2 declaration lines
	class Line
	{
	public:
		/// \brief Virtual dtor, since this is a base class
		virtual ~Line() { }

		/// \brief Virtual ctor, creating one of our subclass objects
		/// based on what we're passed
		///
		/// \param tl list of tokens found on a line in an SSQLS v2 file
		/// \param subdirective true if there was leading whitespace on
		///        that line, which changes how we interpret tl
		/// \param file information about the file we're currently parsing
		///
		/// \return Line object pointer if line was successfully parsed,
		/// else 0
		static Line* parse(const StringList& tl, bool subdirective,
				const File& file);

		/// \brief Print line's contents out to a stream in SSQLS v2
		/// form.
		virtual void print(std::ostream& os) const = 0;

	protected:
		/// \brief Protected ctor, to prevent instantiation
		Line() { }
	};


	/// \brief A list of pointers to Line objects
	///
	/// These are used for holding the results of the file parsing step
	typedef std::vector<Line*> LineList;

	/// \brief Iterator into a LineList
	///
	/// It's const because once the parse is completed, we switch into
	/// LineList traversal mode, which doesn't modify the list.
	typedef LineList::const_iterator LineListIt;

	/// \brief 'field' directive line
	class Field : public Line
	{
	public:
		/// \brief Holds information about a SQL field declared in
		/// the SSQLS v2 language
		///
		/// \param type the field's SQL type
		/// \param is_unsigned true if type is an integer and is unsigned
		/// \param is_null true if field's value is nullable
		/// \param is_autoinc true if DB automatically assigns an
		///        auto-incrementing value to this field in INSERT if
		///        it isn't specified
		/// \param is_key true if field is part of the primary key
		/// \param name the field's SQL name
		/// \param alias the field's C++ name, defaulting to the SQL
		///        name
		Field(const std::string& name, const std::string& type,
				bool is_unsigned = false, bool is_null = false,
				bool is_autoinc = false, bool is_key = false,
				const std::string& alias = 0) :
		name_(name),
		type_(type),
		is_autoinc_(is_autoinc),
		is_key_(is_key),
		is_null_(is_null),
		is_unsigned_(is_unsigned),
		alias_(alias)
		{
		}



		/// \brief Attempt to create a Field object from information in
		/// the passed StringList
		///
		/// A kind of pre-processor for the Field ctor, creating one of
		/// those objects only if the given StringList makes sense,
		/// using the values we find in that StringList as parameters to
		/// the ctor.
		static Field* parse(const StringList& tl, bool subdirective,
				const File& file);

		/// \brief Print field description out to a stream in SSQLS v2
		/// form.
		void print(std::ostream& os) const;

		/// \brief A smart enum for converting SQL type strings to one
		/// of a relatively few types we directly support.
		///
		/// This object defaults to a value of ft_string if the type
		/// cannot be discerned.
		///
		/// This class is public only to allow it to be tested, in
		/// test/ssqls2.cpp.  It shouldn't actually be used outside
		/// ssqlsxlat.
		class Type
		{
		public:
			/// \brief Known SQL field types
			///
			/// This list is shorter than what we support in MySQL++'s
			/// lib/sql_types.h and shorter still than the full list of
			/// types that SQL database engines support.  Its length is
			/// limited by the diversity of data types in C++ and
			/// MySQL++.  We map SQL types to one of these values as
			/// best we can.
			///
			/// This list doesn't encode anything about nullness,
			/// signedness, etc.  Those are considered attributes modifying
			/// the type, not creating independent data types.  We store
			/// these flags in separate variables in the outer class.
			enum Value {
				ft_tinyint,		///< TINYINT, INT1, BOOL
				ft_smallint,	///< SMALLINT, INT2
				ft_mediumint,	///< INT, MEDIUMINT, INT3, INT4
				ft_bigint,		///< BIGINT, INT8
				ft_float,		///< FLOAT, FLOAT4, FLOAT8
				ft_double,		///< DOUBLE, DECIMAL, FIXED, NUMERIC
				ft_string,		///< *CHAR, ENUM, *TEXT
				ft_blob,		///< *BLOB, VARBINARY
				ft_date,		///< DATE
				ft_datetime,	///< DATETIME, TIMESTAMP
				ft_time,		///< TIME
				ft_set			///< SET
			};

			/// \brief Constructor
			///
			/// Given a SQL type string, try to figure out which of the
			/// relatively small set of known values to use.  Defaults
			/// to ft_string if we can't find a more appropriate type,
			/// as all SQL values can be dealt with as strings.
			Type(const std::string& s);

			/// \brief Copy constructor
			Type(Value v) :
			value_(v)
			{
			}

			/// \brief Print type description out to a stream in
			/// SSQLS v2 form.
			void print(std::ostream& os) const;

			/// \brief Enum value accessor
			operator Value() const { return value_; }

			/// \brief Equality operator
			bool operator ==(const Type& rhs) const
					{ return value_ == rhs.value_; }

		private:
			Value value_;
		};


	private:
		std::string name_; 	///< the field's SQL name
		Type type_; 		///< the field's SQL type
		bool is_autoinc_;	///< true if DB autoincrements this column if left out of INSERT
		bool is_key_;		///< true if field is part of the primary key
		bool is_null_;		///< true if field's value is nullable
		bool is_unsigned_;	///< true if field has unsigned integer type
		std::string alias_;	///< the field's C++ name
	};

	/// \brief 'include' directive line
	class Include : public Line
	{
	public:
		/// \brief Given the name of another SSQLS v2 file, load it
		/// up and parse it.  Its contents will appear transparently
		/// as part of the overall parse result.
		///
		/// \param file_name name of other SSQLS v2 file to parse
		Include(const char* file_name) :
		pp2_(new ParseV2(file_name))
		{
		}

		/// \brief Destructor
		~Include() { pp2_->clear(); delete pp2_; }

		/// \brief Get an iterator pointing to the start of the
		// sub-parse's LineList
		LineListIt begin() const { return pp2_->begin(); }

		/// \brief Get an iterator pointing to just past the end of the
		/// sub-parse's LineList
		LineListIt end() const { return pp2_->end(); }

		/// \brief Attempt to create an Include object from information
		/// in the passed StringList
		///
		/// A kind of pre-processor for the Include ctor, creating one
		/// of those objects only if the given StringList makes sense,
		/// using the values we find in that StringList as parameters to
		/// the ctor.
		static Include* parse(const StringList& tl, bool subdirective,
				const File& file);

	private:
		// Never called.  Include directives don't appear in the parse
		// list; the included file's contents appear in its place
		// instead.  Since this method only exists to test parsing
		// behavior, we can't be called.
		void print(std::ostream&) const { assert(0); }

		/// \brief pointer to the object holding parse details for
		/// the other file we were constructed with
		ParseV2* pp2_;
	};

	/// \brief Base class for known SSQLS v2 'option' directives
	///
	/// There are subclasses for all known SSQLS v2 options, having
	/// the same name, but with different capitalization and an
	/// "Option" suffix.
	class Option : public Line
	{
	public:
		/// \brief Virtual dtor, since this is a base class
		virtual ~Option() { }

		/// \brief Attempt to create an Option object from information
		/// in the passed StringList
		///
		/// This is a kind of pre-processor for the Option subclass's
		/// ctors, creating an object of one of those subclasses only if
		/// the given StringList makes sense, passing those values as
		/// ctor parameters.
		static Option* parse(const StringList& tl, bool subdirective,
				const File& file);

	protected:
		/// \brief Protected ctor, so we cannot be directly instantiated
		///
		/// \param value the option's value
		Option(const std::string& value) :
		value_(value)
		{
		}

		/// \brief Convert a string expressing a boolean value to a \c bool
		///
		/// If we cannot recognize the value, we return true because
		/// SSQLS v2 options all default to false.  The assumption is is
		/// that if the option directive is present, the value is most
		/// likely truthy.
		///
		/// As a consequence, the only thing this function recognizes is
		/// "0", "false", "no", and "off", with any mix of upper and
		/// lower case.  All else is considered \c true.
		static bool parse_bool(const std::string& value);

		/// \brief Return the option's value in string form, unmodified
		/// from the original parse
		///
		/// Subclasses typically either expose this function in their
		/// public interface with a different, more appropriate name, or
		/// they define a wholly different method returning a reduced or
		/// more type-safe version of this value.
		const char* value() const { return value_.c_str(); }
	
	private:
		// The option's raw value string
		std::string value_;
	};


	/// \brief 'option accessor_style' directive line
	class AccessorStyleOption : public Option
	{
	public:
		/// \brief Constructor
		AccessorStyleOption(const std::string& value, const File& file) :
		Option(value),
		type_(AccessorStyleOption::parse_type(value, file))
		{
		}

		/// \brief Print the option description out to a stream in
		/// SSQLS v2 form.
		void print(std::ostream& os) const;

	private:
		/// \brief Known accessor styles
		///
		/// \internal We could implement this by deepening the Option
		/// hierarchy, making this a base class, with the known styles
		/// each implemented as a subclass, but that's seems excessively
		/// OO-dogmatic.
		enum Type {
			unknown,			///< bad style value found in .ssqls file
			camel_case_lower,	///< generate accessors like \c getX()
			camel_case_upper,	///< generate accessors like \c GetX()
			stroustrup,			///< generate accessors like \c get_x()
			overloaded			///< same method name for setter and getter
		};

		/// \brief Given a raw accessor style value straight from the
		/// parser, try to figure out which of the known styles is
		/// meant.
		static Type parse_type(const std::string& style,
				const File& file);

		/// \brief Parsed accessor style type
		Type type_;
	};


	/// \brief 'option exception_on_schema_mismatch' directive line
	class ExceptionOnSchemaMismatchOption : public Option
	{
	public:
		/// \brief Constructor
		ExceptionOnSchemaMismatchOption(const std::string& value) :
		Option(value),
		throw_(Option::parse_bool(value))
		{
		}

		/// \brief Return true if our emitted C++ code is supposed to
		/// throw an exception on schema mismatches
		operator bool() const { return throw_; }

		/// \brief Print the option description out to a stream in
		/// SSQLS v2 form.
		void print(std::ostream& os) const;

	private:
		bool throw_;	///< parsed version of parent's value
	};

	/// \brief 'option header_extension' directive line
	class HeaderExtensionOption : public Option
	{
	public:
		/// \brief Constructor
		HeaderExtensionOption(const std::string& value) :
		Option(value)
		{
		}

		/// \brief Return the extension used for C++ headers we emit
		const char* extension() const { return value(); }

		/// \brief Print the option description out to a stream in
		/// SSQLS v2 form.
		void print(std::ostream& os) const;
	};


	/// \brief 'option implementation_extension' directive line
	class ImplementationExtensionOption : public Option
	{

	public:
		/// \brief Constructor
		ImplementationExtensionOption(const std::string& value) :
		Option(value)
		{
		}

		/// \brief Return the extension used for C++ implementation
		/// files we emit
		const char* extension() const { return value(); }

		/// \brief Print the option description out to a stream in
		/// SSQLS v2 form.
		void print(std::ostream& os) const;
	};

	/// \brief 'table' directive line
	class Table : public Line
	{
	public:
		/// \brief Constructor
		///
		/// \param name the table's SQL name
		/// \param alias the table's C++ name; defaults to \c name
		/// \param filebase the base name used for generated C++ code
		///        files; defaults to \c name
		Table(const std::string& name, const std::string& alias,
				const std::string& filebase);

		/// \brief Attempt to create a Table object from information in
		/// the passed StringList
		///
		/// A kind of pre-processor for the Table ctor, creating a Table
		/// object only if the given StringList makes sense, using the
		/// values we find in that StringList as parameters to the Table
		/// ctor.
		static Table* parse(const StringList& tl, bool subdirective,
				const File& file);

		/// \brief Print the table description out to a stream in
		/// SSQLS v2 form.
		void print(std::ostream& os) const;

	private:
		std::string name_, alias_, filebase_;
	};

	//// Exception types
	/// \brief Exception object thrown to indicate a file I/O error
	class FileException : public mysqlpp::Exception
	{
	public:
		/// \brief Constructor
		///
		/// \param what description of what went wrong reading the
		/// SSQLS v2 file
		FileException(const std::string& what) : Exception(what) { }
	};

	/// \brief Exception object thrown by File::error() to report
	/// an SSQLS v2 parsing error
	class ParseException : public mysqlpp::Exception
	{
	public:
		/// \brief Constructor
		///
		/// \param what description of what went wrong parsing the line
		/// \param file_name name of source file where error occurred
		/// \param line line number in source file where error occurred
		ParseException(const std::string& what,
				const std::string& file_name, size_t line) :
		Exception(what),
		file_name_(file_name),
		line_(line)
		{
		}



		/// \brief Destructor
		~ParseException() throw() { }

		/// \brief Get name of file where error occurred
		const char* file_name() const { return file_name_.c_str(); }

		/// \brief Get line number where error occurred
		size_t line() const { return line_; }

	private:
		std::string file_name_;
		size_t line_;
	};

	/// \brief Constructor
	///
	/// Given the name of an SSQLS v2 file, load it up and try to parse
	/// it, throwing one of our inner exception types if that fails.
	///
	/// \param file_name path to an SSQLS v2 file to parse; may be in a
	///        different directory, given a relative or absolute path
	///        to the file
	///
	/// \throw FileException
	/// \throw ParseException
	ParseV2(const char* file_name);

	/// \brief Destructor
	~ParseV2()
	{
		for (LineListIt it = lines_.begin(); it != lines_.end(); ++it) {
			delete *it;
		}
	}

	/// \brief Get an iterator pointing to the start of our LineList
	LineListIt begin() const { return lines_.begin(); }

	/// \brief Dump our line list
	///
	/// Doesn't delete the line objects.  This is used by Include,
	/// because its creator will take over ownership of those objects.
	void clear() { lines_.clear(); }

	/// \brief Get an iterator pointing just past the end of our LineList
	LineListIt end() const { return lines_.end(); }

private:
	/// \brief Break line up into a series of space-separated words
	void tokenize(StringList& tokens, const std::string& line) const;

	/// \brief Information about the file we're currently parsing
	File file_;

	/// \brief List of Line object pointers representing the parse result
	///
	/// This does not contain Line sub-classes for subdirectives.  You
	/// will find a LineList inside the top-level directive class.
	///
	/// You will not find Include objects in this list corresponding to
	/// any 'include' directives in the input file.  On finishing the
	/// recursive parse for the included file, we pull its LineList
	/// contents up into this level.  This flattens the recursive parse
	/// so the code doing the traversal doesn't have to worry about it.
	LineList lines_;
};

/// \brief Write a Line out to a stream in SSQLS v2 form.
///
/// \internal This is implemented in terms of ParseV2::Line::print()
/// because operator<< needs to be a global function.  This trick lets
/// us get polymorphic behavior when writing Line objects out.
std::ostream& operator<<(std::ostream& os, const ParseV2::Line& line);

#endif // !defined(MYSQLPP_SSX_PARSEV2_H)
<
>
|
|
|
<
|
<
|
<
|
<
<
<
<
|
<
<
<
<
|
<
<
<
<
<
|
<
<
|
<
|
<
<
<
<
|
<
<
<
|
|
<
>
|
|
|
|
|
<
<
<
|
<
<
<
<
<
<
<
<
<
<
<
|
<
<
|
<
<
<
|
<
<
|
<
<
<
|
<
<
>
|
|
|
|
|
|
|
|
|
<
<
<
<
|
<
<
<
<
<
<
<
<
<
<
<
|
<
<
<
|
<
<
|
<
<
<
<
|
<
<
|
|
|
|
|
|
|
|
|
|
<
<
<
|
<
<
<
<
<
<
<
|
<
<
<
<
<
<
<
<
<
<
<
<
|
<
<
<
|
<
|
|
<
|
>
|
|
|
|
|
|
|
|
<
<
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
|
|
|
|
<
<
|
>
>
|
|
|
|
<
<
<
<
<
|
<
<
<
|
<
<
<
<
<
<
<
<
|
<
<
<
<
<
<
<
<
<
<
|
|
|
|
|
|
|
|
|
|
<
<
<
<
<
<
<
<
<
<
|
<
<
<
<
<
<
<
|
<
<
<
<
<
|
<
<
<
|
<
|
|
|
|
|
|
|
|
<
|
>
|
<
<
<
<
<
<
<
<
|
<
<
<
<
<
<
<
<
<
<
<
<
<
|
<
<
|
<
<
<
|
|
|
|
|
|
|
|
|
|
<
<
<
<
|
<
<
<
<
<
<
|
<
<
<
<
|
<
<
<
<
<
<
<
<
<
<
|
<
|
|
|
|
|
|
|
|
|
|
|
|
<
<
<
<
<
|
<
<
<
<
<
<
<
<
<
<
<
|
<
<
<
<
<
<
<
<
|
<
|
|
<
|
>
|
|
<
<
<
<
|
<
<
<
|
<
<
<
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
|
<
<
<
<
<
|
|
|
<
|
>
|
|
<
<
<
<
<
<
<
<
|
<
<
<
|
<
<
<
|
<
<
<
|
<
<
<
<
<
<
<
<
<
|
<
<
|
|
|
|
<
|
>
|
|
<
>
|
|
|
<
<
<
|
<
<
<
|
<
<
<
<
|
<
<
<
<
<
<
<
<
<
<
<
<
|
<
<
<
|
|
|
|
|
|
|
|
|
|
|
|
|
<
|
<
<
<
<
<
<
<
<
<
<
<
|
<
<
<
<
<
<
<
<
<
<
<
<
<
|
|
<
<
|
>
>
|
|
|
|
<
|
<
<
|
<
<
<
<
|
<
<
<
<
<
<
<
<
<
<
<
<
|
<
<
<
<
<
<
<
|
|
|
|
|
|
|
|
|
|
|
<
|
<
<
<
|
<
<
|
<
<
<
<
<
<
<
<
<
<
<
<
|
<
<
<
<
<
<
|
<

1
2
3
4

5

6

7




8




9





10


11

12




13



14
15

16
17
18
19
20
21



22











23


24



25


26



27


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



56

57
58

59
60
61
62
63
64
65
66
67
68


69
























70
71
72
73


74
75
76
77
78
79
80





81



82








83










84
85
86
87
88
89
90
91
92
93










94







95





96



97

98
99
100
101
102
103
104
105

106
107
108








109













110


111



112
113
114
115
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
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
191

192











193













194
195


196
197
198
199
200
201
202

203


204




205












206







207
208
209
210
211
212
213
214
215
216
217

218



219


220












221






222


C Version\s3.2.0
D 2013-06-21T02:05:50.000
F Bakefiles.bkgen 1378c0673a35d047724db07b75b53dda4edac3532f50f287a286154c3068cac0
F COPYING.txt c943babbd1de963894a9ba8583e8f50cdc7a6ab7c0522a0251c8cd21caa9f672

F CREDITS.txt 9f8804156fe7d6266312bec64d810aeaa3b9cc683615619b8d8c63d18f806329

F ChangeLog 93c9b115c85180f613520b0c33f45efbdcf253c3d67acfaf37ecb6278912ea4f

F HACKERS.txt 6f1c4cfc77b41d80064c819f28eb77e732e7a9c3d0cee5bd64d8dd08b757b84c




F INSTALL.txt 34f34084bb61b1092c2baaba90fb48723010dbe50d09acb5b170820aafad41b5




F LICENSE.txt 97ebb45ce18ea0be5a31a8aec2228eee997e3ed3df0aa31771ade1999d483a82





F Makefile.mingw 11723c6ae185158eaa01006f5d70c36e49601fa3dc13605db100684d9dcc3804


F Makefile.simple d5078fcef531682d50f59d317eed2da7dbfe2ed666f58f3768e634d488113ff7

F README-Cygwin.txt fb25857013841a657741c323acb61cdf4f168efaeff705d2e5973b79f5eb960b




F README-Linux.txt 418e01796ed0bc9b54ac87aaf2d38da33845e26c10fb04e77a9e10ad2ee01fb2



F README-Mac-OS-X.txt e8bd6329fa524099e0e2ca7fc3e4576a0b0c1b7a6ce3fa562a144cce92f68d67
F README-MinGW.txt 5b4eaf81270ae701b2ba5b4eec5b3a9036b34cd429436c9eeb3b168e3ea32e2d

F README-Solaris.txt 17bab66b3620f84a1b18c99a88abf447d46ad915888485e8dc4ee6a3c7898c9e
F README-Unix.txt 65a51383a2c799e01c620c3175fead5a52ba031e22685b24c5730463a4763c8d
F README-Visual-C++.txt 8f91bbd15f5721879b32b5dc6f6333b8d7ea9cc6ea104e9c5a28d62074b10b5f
F README-examples.txt 1e9e6a1f8602029653bc44120a36c1e50fe583b5489639081f745255f18400a3
F README.txt beb3b1247585cc45b04d82a823dd81d43f81ff6e8a468d956d3a5d5b42fe93dd
F RELEASE-CHECKLIST.txt 367e2197607e1d5d5160ed5aa09cffc0c0a800e77125149b55f6c5dbf1638093



F Wishlist 69e030a4ae21ccccd8a4391ee278770607895e519332689b84700382ac42e142











F abi.xml.in b977dd2983a3b8e33d4330ba697a4c65ce21e7b58f79ee431c906d761a6a0894


F bk-deps a506e067bfde55305e097815f1e11febbcbaf9c0493ef804b4b81dfc1a60f34e x



F bmark.txt 973d955a0625b12f5f9045fb31b818c0d24a17926320c3e2a1a94e3d2f778c39


F bootstrap 32f8830cd6835d0173ca1f2ec746f3a155ddf0b0d39d1b6406ea79e5402338e8 x



F bootstrap.bat 8c501dacd4993d4bdf43a67f1c6645b22c85fb03f36b423600a2a68c36ce75d2


F cleanmf e385426a032ada497be42ff7504ef1fffcccd34635af530c25f19e2f209ec653 x
F config.h.in 1b90cdeaa1cd12018a912cb86d61d1cf6699f97f8fa7a0b546f4936133c7226f
F config/acx_pthread.m4 8a9dbf4783b282f82c062edac20886e75e0ef9d555ac59b0dad68f1559a3a460
F config/autoconf_inc.m4 7d57c517f5a4ccd2a6d97c7904feaa2bc1089fa020e0e65b75f0b54e9a36adef
F config/libm.m4 de3dcf0b6e8149f13c9e26dcdeaf25bf5b40fa3993546835b29c0a3be6ee63ea
F config/localtime_r.m4 8ba2bda9bdf152d8f901180b2eec716f75c381c5ed2d98666f4f0cfe29152256
F config/mysql++.m4 a305b5d0f8c47b51e487381ef4e38f4acc63683b2d10c9c15065430044e4d207
F config/mysql_loc.m4 b8b47767ca53e976578d4dcac16493cdd06a511c48cd6a7f2e12c012d51cf696
F config/mysql_ssl.m4 4ef297a027b01f69e7e4669fdd2e86f1e8542b484fd37307c27da76525decdd5
F config/socket_nsl.m4 6dd364d066feec0abf2b2bcdd377710010c459d3c6fbedad77a20f38997c7de2




F config/stl_slist.m4 614e5c3929b7b506b1f61ce6a4f089a5ef5acc049a0920963a32dd2bd11ad7c1











F configure.ac 798243d1c59a473bb30e8b7151cd44c62dca20d0df53fd2e57666134f7de9c5b



F doc/README-devel-RPM.txt d920bb8de3af6578f5cbe1d41b53010b3e0c37163ec8226aa708d1aab869ec83


F doc/README-manuals-RPM.txt 12316b39e05f17d22d378647a574c7f6d1a12bca86ca75c54e761555b9f34763




F doc/ssqls-pretty d5f23af891a27583871e0bc1dd3c3df1f43eb6ce02e8ba06f69c3b5a82efedc5 x


F doc/userman/Makefile a7add9114d4f7b6a23479ee42f7311815f80390796ddae5e2157ca80a3a1a76a
F doc/userman/Makefile.hello.mingw b449195443182ad502dde9ee8872ba537edfae2bb0334722959dbafb98a2b179 x
F doc/userman/Makefile.hello.posix 1d3246fbc93fa02e7a9b2e84ba0ef32f27213789e49e6a4c95ad05685b9b2ade
F doc/userman/breakages.dbx 79dec0d4506d735a4f1c8d0519bb5f3d03dbbf8b2be7c4f094a03f8166101905
F doc/userman/common.xsl ec35926ab1e3a6c06d2df9ddd383e6d6cc2736db2385b193d08802d9190d58ee
F doc/userman/configuration.dbx a9b31160135a6eaf2403e070b4467cb20eed36d1c199c2a5e72b2873303586f0
F doc/userman/fo.xsl ac5397b661eb25507f9709f3e420b0d6be899d5bbed5c2cbff5c76b1a09ceadc
F doc/userman/fo2pdf 74eac534227f7f124d5cf3fa24b550dbb78409af472fc35b166cee852da1f582 x
F doc/userman/html.xsl acaffa4de9387b095cb9bc22508d5bebfeccb5c4c506bb067ca0dc881536b554
F doc/userman/incorporating.dbx 80e9fced7de50f9dfc1ab57940d3859d95e3b6f9a893599676984e5f0c11c75d



F doc/userman/intro.dbx a0e634330659449d3684ae2882e9a2d521a46a36382aefa4d04bd1bf49498eba







F doc/userman/licenses.dbx 9cbaec5d5d90c5af2f2ee9c9f15f022a7011508741c4feaf3f0f3fe8f1bb5fac












F doc/userman/mktxt d7fb06e2c293cb0106ec5ba5508757022740f07e79f96065925735fa11506374 x



F doc/userman/overview.dbx 6ceb7c85beab820f19c8c7ff1f42b542eeece43909aa0bbc3ca74df50ed1b44a

F doc/userman/section-template.dbx 258801d08cb6774a5063c2f92cfaec176712cf47f68641bf724e4a944c02c70a
F doc/userman/ssqls.dbx f4bb6f36e0725fe5062a0a8b8af16a0fe62a9800a242dfd4339844b942b23106

F doc/userman/threads.dbx a7a40bffe0c9a8adc6a5fdbf17bb2659fee1927377a45e706a1648a8d3a0b71d
F doc/userman/tquery.dbx 13530007922f624dce13610e930cf9612966575ecb52ad578ba7cc410611c22e
F doc/userman/tutorial.dbx 3a460c4f3e66b1f9e32bdaac703a7241ff92becc9c88569928af7f800ae6fa1d
F doc/userman/unicode.dbx 245cca9ba6f1a8cbf6cf3113fd54594ed221e0fd65be60ef67d4852f7542f3db
F doc/userman/userman.dbx b29187e0d68f0331eae86f1239347139303b25109553b0d77ea9715a6917ea02
F doc/userman/userman.dbx.in ec604d72ffd8c184e934cd2033036d102c6d35ae097e585ee13995e99a199842
F doc/userman/xinclude.mod b04b9b28807b9abb457dddd72d8df3548347c56dd5d69b97b762f457eabf01fe
F dtest 257ddf48697e9841107610031187e5c9676118fac4ba3de9e753140f91056001 x
F examples/cgi_jpeg.cpp 41c856cdd9a4c36f2130e08b11fae4a4983cf747282a50cbab99006d0bc1f5b1
F examples/cpool.cpp e695c44737d7b68dd6cfd562a8e82cddaf2a835b314d81b0fafec2ff29bc1858


F examples/dbinfo.cpp 9c73702befdd5ba82364634d47fefad8ef164d54dff80fce5bd6d2d67af70a1d
























F examples/deadlock.cpp e2d48b901cb0c9ef8e2e18050754f874489fa76eb944b55e8120211ba5afbdd7
F examples/fieldinf.cpp b92f510ca75e331f27913c3da776f7dc4ea5e6a17e0ac9d39beb1b89806f2c3b
F examples/for_each.cpp 3efb48e69dc820480f465c4af927e12937b0df6e3345ea7ede39a22a3f34d2ff
F examples/images.h eff98d54763fcdc1ab8e58ab71648f74554d192b9d7bf99b93669de65e70fa30


F examples/load_jpeg.cpp 5259990f5295ef68299d39d229076fa6835d8eed9c050137e9b09bad4a142886
F examples/logo.jpg b551f2a4609684c83c17acc32faa08af659df397aba70fe7e0f12de82c4bc934
F examples/multiquery.cpp 742d8707efdf9b1a8c0c531a6f81e2b324e9745fbbd9565e53f5d2dec2507a9c
F examples/printdata.cpp cabfdb65b121a0ada9cdd67379d458b8b77eb69d60a44a369c73dfa036700fc9
F examples/printdata.h 201ba1d04b99ef5db9d69d99f985d41fab983a12810c4e16b9a433287c92b483
F examples/resetdb.cpp 758eaab06a2daf476205ec14e9f957aa178bcf91dfe425ff56e8dd7f8fcb0a67
F examples/simple1.cpp 8140c09587cebe3d8f97ae0dafe29188b5578d26d58adeb7c81e1f5faceb9a4b





F examples/simple2.cpp e4edb4d49033848ee82c54d5b6d46f3318bf44c56d5959719ab6f7eaa7f0da60



F examples/simple3.cpp 604fa7b0dc9b1f7677a7088493b8fa25014bc38f42f79f9002f95c63967c3389








F examples/ssqls1.cpp 26c1a1af36aebcfc6a0adeaedddbc3eb9bbd302933cdb50a5dc275146f03233a










F examples/ssqls2.cpp faead49be3a339b0817fa74b77f16240895cfa4ebbe85f067ad721e4b0475d61
F examples/ssqls3.cpp 5f776cd5de0a9e1b79b4431f66c89dabe26f52a205f0580a60703ce771c14a61
F examples/ssqls4.cpp 4a0ba3becc091fac4003ff905daef1f6644cc9e992b6714e525ac50ccaf472b9
F examples/ssqls5.cpp ed53e908e3206d61081485c8ac327abc237316240f047a91415a69a71bcd2e69
F examples/ssqls6.cpp 71a4d0b2256e288318dc460ba72e46a97c883451269148dc130757bd1f8cb886
F examples/stock.h 7a27e43688f7fb40e19ee36ae6637ad93aca88f4d72a45cc4fea06ffbcd77f1e
F examples/store_if.cpp 0adea2de699079171e50d65e77c67d768d0f0face939b59146e220a442d80358
F examples/threads.h 78091cf6989ba263082a8aade1b1fa1d64130f5e2d5e353e5afcbe7c6bb4fbed
F examples/tquery1.cpp 6c6965a13411541a923f44e69f442a53aadac50c49192963fb982c3aeeada802
F examples/tquery2.cpp 96a2a408d852707bcbd7f14cfa823fb8331763ac752b445e4f5acfc3bd3fb94e










F examples/tquery3.cpp e0e53072caeffe9e3944a3bbff081cc2751fe9342e15eb98168ef17fcfe686f7







F examples/tquery4.cpp 753892f736a61afa926cdb1eab7a34c1ebd6f4b5dcbb39b21aaafe50bed1c909





F examples/transaction.cpp d1b310ebbea4cfe14f7c8656db8485b8ab6416eb9912f7911001fad02db25d4e



F examples/vstudio/mfc/mfc.cpp 81bc84b78340d7e4fba2c850f4b25720ad7fcfb4d58fefe1cce3c3ed9bd2e019

F examples/vstudio/mfc/mfc.h e1da8ccc157701e5c208cf8b24b51cf08d8f13b48a8809d8223318ad813991ab
F examples/vstudio/mfc/mfc.rc 7f893118cb86cbcbf8a4d4d30fd5f122d7b7916895aba82327c770354dbd842a
F examples/vstudio/mfc/mfc_dlg.cpp 5b2eb625d7fb07648b9a0429490a0812b186e237b2cd690025f01483356cdaad
F examples/vstudio/mfc/mfc_dlg.h eb5ba79ffe166455e27601b94642566de7822a87329661abac15f4e200f7bb72
F examples/vstudio/mfc/resource.h ca71f958b51bf17dfbba0d1591211efe36187ef869b6bff5e0dc9a59cf40a2f6
F examples/vstudio/mfc/stdafx.h b5a1c41c2a252ab4275ec9d8a584f058c4596c2c6d767ee756a4f4546ea86fd1
F examples/vstudio/wforms/AssemblyInfo.cpp 08e3cfc50233132ea5d4b70b47fa2bce669c2c6a97896f8b0ec62b882e1deeb1
F examples/vstudio/wforms/MainForm.h 0f3c1f1f59d50683e262a07c2db28b2eba3dbcdc23f190354b18f7b41444781f

F examples/vstudio/wforms/MainForm.resX f69089f338845d493eccdd05a2650a7f3cca9f0993f746723d7f7d08054d681f
F examples/vstudio/wforms/resource.h 3c4a478a4643ae9ccf7988df1613197a7f4ab3483455c8037004c6da26b036e9
F examples/vstudio/wforms/wforms.cpp 6566a4a77faae13ee3bdd474c347a62e68632c5f6b053194aa40d12689e4a160








F exrun 4450f57cd0ed563925652e0fc3af646a0fa471138831c1e120ec534aa65dd948 x













F exrun.bat f1884f9c023c322373f814e7d70f6488771569f4035c7d1697d970b7bb9e893d x


F install.hta.in c154df770e08f8b617f9aed85dbfe54e2650e64ab63f6afb791a3a00829ed678



F lib/Doxyfile.in 51e34e4f978e41507449b220fd16c2501e2eb8c5c11384cbd37c15d91ba6603d
F lib/autoflag.h 58f79df863e952a15542a0001a87a037af86b9014bc3787f99489a404f502957
F lib/beemutex.cpp 729da280560845acae28d48d5c01455713ef87c358637279600dc254442c19fc
F lib/beemutex.h a88f946fecfdf1f998a3fa1c33764cd8001e45fe17ee8c2db0cdc38dad54e4d7
F lib/cmdline.cpp 45184784697a5dae9bfcfc67a5aecf80e13b5149ea1f5d9ecd42ce88ab0aa417
F lib/cmdline.h 53678455c3bb2de7a6af5b89d539e5895ee99649a6183340778b8bbd9cbfe794
F lib/common.h 870e62ebff29f43e0f27030c433c6e7dcc8b42f079f8012b2987a00976aafd01
F lib/comparable.h 4abef254c194319823ad527991d2f1065f24fc435439469e2c7795c8ba563471
F lib/connection.cpp f3c0a4823a619d0722de585f96548e9d8aa3f9d0de9a88604e5f8b6bcf63ffde
F lib/connection.h b76a8d178d4f1f730a9cab645112fcbfbba80c50e2bc2eca671527809febea18




F lib/cpool.cpp c7e9798763fb203a2a2b662371b5cd1f9a356551866f1f6f83c662bd5a4038d1






F lib/cpool.h 0f199b2b65847bb3b5e85388b505d3b6d1d0a16069256db3b6f46ea6f676f3f0




F lib/datetime.cpp efcef86ddea19a3d99db91df4d9816e5cd0cc6d044ecb774a41f8738006a5dfb










F lib/datetime.h 3a5f9ec152eace11864527c907bf8f9543bb96a939fb1f23a129133432ade11f

F lib/dbdriver.cpp 2b99a8b806cc5ffacf12e12df69bb526676d3a21e737b0fe98927383f33f840b
F lib/dbdriver.h 4778a6b5e2ae6739d0f8868fb126728be4e9113813e711fd34a6a389b9c8fe3c
F lib/exceptions.h 45fc9a816fd4222661dce0b8f2649be7a9c22fdd9427e54dd8fd9b355939a53a
F lib/field.h 0e52ca8dc9377690ca6f0ae8a70a0840ddaa9132eba233ea1f558a00a74b748d
F lib/field_names.cpp 5b07458d72e3b75703dc0a499be7788470c1999fd66bd979d7c05a6a1b078e00
F lib/field_names.h 0291d3307f2b96f3a71dfb0ebaa14598f3152a48bfbb9eaab798bbe4e7700182
F lib/field_types.cpp f398720812c018c158c218a6e22959c908973ede7231dcb76b7bede546b8b16d
F lib/field_types.h f42e8d92974d7043b5f82e7c6f9772f0a05e61bfba7fa7761a2427c306beea18
F lib/insertpolicy.h af2681726f5119025fbb1056fcf0a30b26bfd638763cf29a236b90b7580187fc
F lib/manip.cpp 9dc4486fde9f360bcf05497bfca1dc95ad7d2367c5806240dfd76f48d2af56a8
F lib/manip.h ec92e560792a7ae7418e6f766fc2ca70efb6d6c2892707bf1c2fa152e4e8c370
F lib/myset.cpp 462c808158c304a45340a3bcb04bbfe25ecc36103ad2b88812f2efe7b1cd9f00





F lib/myset.h 24521ab1b8db1aa23215d8f7132235107921ff5f97998139080325518c49a9b1











F lib/mysql++.cpp b6a0f2325a8c5fa6d3483c95ff64130de75b82ae090505ccb6a434d9332553f1








F lib/mysql++.h.in 66adebeaff1ad5a4a48ec252d2afc391519d7e4c89c6087ff90aff57310d34ed

F lib/mystring.cpp 91086ed3a3bd79e622c3de4c440f5e83260147b7c4ea641bfdbb3a0001bce2d2
F lib/mystring.h 73a5dcf949b42550ac639ff2d846826ef53634d73238f7caa696242ef035eb46

F lib/noexceptions.h 90b154a5656a36c65a598a6907dcf70478517b8d7aa1ab5747d034146e764ba8
F lib/null.cpp 29054e85daa1a2df68d638c5745924906e8479344e057f8b1f8a151b3ced7fd9
F lib/null.h 885bb0030775f0abf6e3ea62975d5e80b14b3774290466b8bc6c0475e15d945b
F lib/options.cpp 0e19d7f530501f79c747c6a60f7d8f4e53fc1f17474da38e50a6794608346c99




F lib/options.h e426a7427be8fd7ece43c1a2a23704388cbff8cac998742d67bd7d3f6a5e9864



F lib/qparms.cpp c3c7ece6a8cf4381813feb977ccd21cf076aec1af0b5056b0b2bbb12c1cfdb40



F lib/qparms.h 79db4335641deba0db8f107584357de812eb34554054572a5a3b0eb3288e7a28














F lib/query.cpp a0d3e3a916f5ae4c4899294be4cbf03c6544017e6465f7481bbe3dd81ca31543





F lib/query.h 77b0211f2c290d0332091591736f1580f0d9044cf8824ae124d36f01c6c75f78
F lib/querydef.h a42f3204b27062fd462b4f4edca9f904e89b01310a4683b194ca4720f0994771
F lib/querydef.pl b79a8d4d97fe46bd5aecfc01a3247723a406c5a5ec3f97467b900aee32c2c60b x

F lib/refcounted.h b547dd6a84a3959debe10b4a6c6848e0e85c62f81ab7c817757ca08435ce5f1f
F lib/result.cpp c607b01012068721ef1a9368de745823f161c1c54269d89c45f13bcbaa9edfcd
F lib/result.h 45a3d9569eea39511ffb851e16dc42d2c2e19ccc800d49659cb2511bb77f6cad
F lib/row.cpp 4ba4e766292db1bdcee4900b1af50d2f651bae82513e5d9eb482383333e9d6df








F lib/row.h c5b3593b15455839b8cb834ba35f6191927122400b410896f237aceceb99b286



F lib/scopedconnection.cpp 6df0bc476d007b09774d7dbb40cfaf1fd4c573d74c4a34ef30a3c1a777e4a9e9



F lib/scopedconnection.h 146a49b448e61c0cbc4ef86b11160830b5df42fd1c9e3c0c5f1191199ef734d0



F lib/sql_buffer.cpp be96654c01d929005c17e934a12d1b9f20ae25c4badd86816370f60000c77ecf









F lib/sql_buffer.h 68c0b526af54a2eb3e17b68aeeebde1d525360068992ba28b6620ce5691dedf8


F lib/sql_types.h e121e529fce8e070a476d79e83d5dfa3049bf48718b38e3a68d179df84c86159
F lib/sqlstream.cpp 991164b05a878f4ee3d1baa426d9051e9867ec5d2621515ba57e529a5b75b943
F lib/sqlstream.h a4734317d1215fe89fda7c98db76bfc17219538af03d817d39d777ee24e90d84
F lib/ssqls.h c1c3820e0827939d3df82c8d45bea779fa2b4a56c6d857bdf287eabd3995d9a0

F lib/ssqls.pl 78947795fb61195bb4c168edcad265402148d2371b445b1dfe27bbbeaa827fc7 x
F lib/ssqls2.cpp dc09245b78971a66cc6355a97fe94452069727521b220cd06565b8509394867f
F lib/ssqls2.h aed72d98f892b9ab4794e7a74eb0499a1e8ee81e1be1bf6e8eee3712c751d923
F lib/stadapter.cpp 293aa63a38226de8bf141756f6ef03bace592b3636f2b1b75522b69b2dafa7fe

F lib/stadapter.h c4d6a12f569e7999d121831fa80d3639b7502f640cc9d4562a98eef443f400cb
F lib/stream2string.h 602da8de8b7273ac144bca3e120982754071ec64e43003f512931e206cf5f536
F lib/tcp_connection.cpp e2b1a929088f62d8ad8ab79561356c3d30b0e8a5a0cf4d529231f3669a67b8b7
F lib/tcp_connection.h e1faf059e010075cf7f7ddbe51f2a6fb7558ee2ea5ee7c3da6599d7fa00a3cbb



F lib/tiny_int.h 93e87d50703c4871eb237bf88918ad0a7147c4f4abc7f3475c07fd4b2817825c



F lib/transaction.cpp 02c4297cac22932c6dcbb53e128293077c5757dfaee68f4bf116905d5d8dee86




F lib/transaction.h fcfcbfdc2784cd7865da4ecb5599ba2d81a3d8b0d3b20fde3d622fdcd57e5496












F lib/type_info.cpp 49545f109dce70d56c2916d98aef98c18e6b21a33e25e7c8601ff28534747e5e



F lib/type_info.h c5e26d4545acc1f15a95106b47f7d9e1a42ba2f9e3ddb0b8d653c4b9e2b38a1b
F lib/uds_connection.cpp a352c7da19ce1edf8ee57db3ab249af839fb6f7ccd0983146bc25c4087ae2f7e
F lib/uds_connection.h 4f35bc022706e0e03f68a5b5b727c709762af0ed9d674375f3f276e7d3cd5c59
F lib/utility.cpp 63e396efbf46336a08bbb56caf9c1a2642e396f29df22339df77b6c1616214ac
F lib/utility.h b4e321364dd5a98972e8100063cb7bbc83bf2cfbc09fa8f43b093d54dbfe69cf
F lib/vallist.cpp 9ea8d22a4e9c4326e5f5bd6e4dbbc9a5baa114cf4d197d46671fde3a3f945242
F lib/vallist.h cbbae0e30b0185301274d72cbf05d2c4f6ee1b06003c1978a651700cc45171c6
F lib/wnp_connection.cpp de966c60fd69b4d62c6e2cdf8e8741a40297d2d99207cfd2bed2f039b3a40cb2
F lib/wnp_connection.h bccc35d1af3f637f78f1dd400ef873017550ab3a896bedfd17a7614b4998fb24
F mysql++.bkl b1b8dd59c17348dd7594f58fb7d22bb49ad41c0505dc41c29ff9176a829b7120
F mysql++.ebuild 007ec3580f0562fb5db37f2ce011bf4cc797e9449e1e2b61ebd03afd57e57c51
F mysql++.spec.in ecc51cff6a7758f0c7186fef5be013873bea924507a81567f0195eb038523758
F osver 034cabb5f0517c3b0a3bedcf712289fd6b4b205ee9576940a1440dc85060c230 x

F pretty.pl 011358a7e49ceab10b1bcd5e8484edd2b28e3874723ffa95677b79f74ae7e010 l











F rebake.bat edb44b9acedd5fb9008b2f66a96f3e5dc525128384487a6ce52e9c5fbc19408f













F ssx/Doxyfile.in 1ef7363623fa70373ff7ee001b3adf647019104f44bc861adebb092928d2c7c4
F ssx/genv2.cpp 02dae227776f3eb71eb2ccd4991f5eec91c10c9be039c7ecf0aed9d10bf22100


F ssx/genv2.h 86b0944613f461c68b00703b1ee5cdbc99e773181f8ace99cc274cd1e08c76fa
F ssx/main.cpp db1743722b6f2868b00e95e0dce6a9f39f12aa9b11d28984e415d816ea853078
F ssx/parsev2.cpp 934b8385dd2dd27d9c2b7818f5f19667a0b7725e85d596d441cbba79a97e02ec
F ssx/parsev2.h de6fdfeecab8a96849ad351a32c5f83269bcfb99c88fb3e49cce129962856015
F test/array_index.cpp adbceb7e9e7e403a2a4484e81eefa5d13759e70987850c2e77ac10978256b46c
F test/cpool.cpp be6de03a0a847eea8f730ef35833447d278980c436c76bdf44f1aedcb20ed2d3
F test/datetime.cpp 9047e5ebbe9ace632bc89f529b26357a2fe7ac4d37bab5a60a6e6e241a60d57d

F test/insertpolicy.cpp 5a7114d4d9fe8c261dd3ba0aa919ae41cecbe3984a6609cc37b5611a794284ee


F test/inttypes.cpp c34b5e41c64b48283b0964c472e6c4ab1ecc1a328010e4cb406707a47f770ec6




F test/manip.cpp dceda6b2c16a4008cc5cd34503761b20268b023bc3d3e6626b62dd9538f31742












F test/null_comparison.cpp 75a312a0eccb4e6f31ebb0aa99a30590d6f97cad6df55bd462c09b3a93daec22







F test/null_uniqueness.cpp 2f559c7660e199105942c9e8e5078e9879ac5f6b12f8a58bc15a05a824b49d7c
F test/qssqls.cpp 5473f4fdba4870218fc36ac87d5bdb8e287fcd455260d2d297ebb43da1f2533c
F test/qstream.cpp 18be87d072ad4164261eb1c11039624a611cc057d9425b253afe7008832ad3dd
F test/query_copy.cpp d0d217a8e71dfb8c642678e53d3e069bd24072bdcbc0d4c18eebcbd4b3568816
F test/sqlstream.cpp 11254c5fdb9cfd0402d161770f428bca3f2cb17707d598f55bb39b8854695f8a
F test/ssqls2.cpp f302f79b2eff7e22088182d59f89e3508fbb5e663e670e24d21fe2d9910da0d9
F test/string.cpp ca2fea6f0d7cb9a394b28072764617ba1e50cb00de75ed9e78b2770a1cf1809b
F test/tcp.cpp aca2d45cd823a794cd56785d27ef1ef2e04cd4c5e7ca4a010b10ee08cb7f7042
F test/uds.cpp 31e025a2e6f475df255f3d8b6804b05bba25df96c691d5735208e283f099cb71
F test/wnp.cpp e78010d72bcffaf470d96d4dffb4889550f3c38fd0ab3d992b41e4297f224f92
F version.in d74e1616b35e78d414f7b4958f6daac2e2c28d30318c0ffbdefbd2ee4b9b6744

P f18e1d074892acae0f939ae5d830a29450c317ea58b02641ceba89b23e2cb719



R 57c7fac25f60651915e65ebe3916e614


T +sym-v3.2.0 *












U tangent






Z 404fa394525737c7d94a1a7cf362da09

Changes to test/array_index.cpp.

1
2
3
4
5
6
7
8
9
10
11
12
/***********************************************************************
 test/array_index.cpp - Tests operator[] and at() on indexable objects
	to ensure they throw exceptions when given bad indices.

 Copyright (c) 2008 by Educational Technology Resources, Inc.
 Others may also hold copyrights on code in this file.  See the
 CREDITS.txt file in the top directory of the distribution for details.

 This file is part of MySQL++.

 MySQL++ is free software; you can redistribute it and/or modify it
 under the terms of the GNU Lesser General Public License as published

|
<

|







1
2

3
4
5
6
7
8
9
10
11
/***********************************************************************
 test/qssqls.cpp - Tests SQL query creation from SSQLS in Query.


 Copyright (c) 2008-2009 by Educational Technology Resources, Inc.
 Others may also hold copyrights on code in this file.  See the
 CREDITS.txt file in the top directory of the distribution for details.

 This file is part of MySQL++.

 MySQL++ is free software; you can redistribute it and/or modify it
 under the terms of the GNU Lesser General Public License as published
21
22
23
24
25
26
27


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
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
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
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
 You should have received a copy of the GNU Lesser General Public
 License along with MySQL++; if not, write to the Free Software
 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
 USA
***********************************************************************/

#include <mysql++.h>



#include <iostream>


template <class ContainerT>
static bool
test_exception(const ContainerT& container, int index)
{
	try {
		container[index];
		container.at(index);
		std::cerr << "Bad index " << index << " allowed in " <<
				typeid(container).name() << '!' << std::endl;
		return false;
	}
	catch (const mysqlpp::BadIndex&) {
		return true;
	}
	catch (const mysqlpp::Exception& e) {
		std::cerr << "Unexpected mysqlpp::Exception caught for " <<
				typeid(container).name() << ", index " << index <<
				": " << e.what() << std::endl;
		return false;
	}
	catch (const std::exception& e) {
		std::cerr << "Unexpected std::exception caught for " <<
				typeid(container).name() << ", index " << index <<
				": " << e.what() << std::endl;
		return false;
	}
	catch (...) {
		std::cerr << "Unexpected exception type caught for " <<
				typeid(container).name() << ", index " << index <<
				'!' << std::endl;
		return false;
	}
}


template <class ContainerT>
static bool
test_no_exception(const ContainerT& container)
{
	mysqlpp::NoExceptions ne(container);

	try {
		container[-1];
		std::cerr << "Mandatory exception suppressed for " <<
				typeid(container).name() << "::operator[]()!" <<
				std::endl;
		return false;
	}
	catch (...) {
	}

	try {
		container.at(-1);
		std::cerr << "Mandatory exception suppressed for " <<
				typeid(container).name() << "::at()!" << std::endl;
		return false;
	}
	catch (...) {
		return true;
	}
}


// Separate test needed because string indices work different from
// integer indices.  Exceptions for bad field names *can* be suppressed;
// SSQLS needs this to support population of partial structures, with
// the un-queried fields getting default values.
template <class ContainerT>
static bool
test_string_index(const ContainerT& container)
{
	// This test should cause an exception...
	try {
		container["fred"];
		std::cerr << "Bad string index allowed in " <<
				typeid(container).name() << '!' << std::endl;
		return false;
	}
	catch (const mysqlpp::BadFieldName&) {
		// Good; fall through to next test
	}
	catch (const mysqlpp::Exception& e) {
		std::cerr << "Unexpected mysqlpp::Exception caught for "
				"bad string index in " << typeid(container).name() <<
				": " << e.what() << std::endl;
		return false;
	}
	catch (const std::exception& e) {
		std::cerr << "Unexpected std::exception caught for "
				"bad string index in " << typeid(container).name() <<
				": " << e.what() << std::endl;
		return false;
	}
	catch (...) {
		std::cerr << "Unexpected exception type caught for "
				"bad string index in " << typeid(container).name() <<
				'!' << std::endl;
		return false;
	}


	// ...but not this one
	mysqlpp::NoExceptions ne(container);
	try {
		container["fred"];
		return true;
	}
	catch (const mysqlpp::BadFieldName&) {
		std::cerr << "Exception not suppressed for nonexistent field "
				"in " << typeid(container).name() << '!' << std::endl;
		return false;
	}
}


template <class ContainerT>
static bool
test_numeric_index(const ContainerT& container)
{
	return	test_exception(container, -1) &&
			test_exception(container, 0) &&
			test_exception(container, 1);
}







int
main()
{
	try {
		return	test_no_exception(mysqlpp::Row()) &&
				test_numeric_index(mysqlpp::Row()) &&
				test_string_index(mysqlpp::Row()) ? 0 : 1;


	}
	catch (...) {
		std::cerr << "Unhandled exception caught by array_index!" <<
				std::endl;
		return 2;



	}

}








>
>



|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
|

<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
|
|
|
|
|
|
<
|
>
|
|
|
|
|
<
|
<
<
<
<
<
|
|
<
|
<
<
<
<
<
<
|
>
>
>
>
>




|
|
|
|
>
>
|
<
<
|
|
>
>
>
|
>


20
21
22
23
24
25
26
27
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
56
57
58
59
60
61
62
63
64
65
66
67
68


69
70
71
72
73
74
75
76
77
 You should have received a copy of the GNU Lesser General Public
 License along with MySQL++; if not, write to the Free Software
 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
 USA
***********************************************************************/

#include <mysql++.h>
#define MYSQLPP_ALLOW_SSQLS_V1	// suppress deprecation warning
#include <ssqls.h>

#include <iostream>

using namespace mysqlpp;

































using namespace std;



























































sql_create_19(test,
	19, 0,
	sql_tinyint,			tinyint_v,
	sql_tinyint_unsigned,	tinyint_unsigned_v,
	sql_smallint,			smallint_v,

	sql_smallint_unsigned,	smallint_unsigned_v,
	sql_int,				int_v,
	sql_int_unsigned,		int_unsigned_v,
	sql_mediumint,			mediumint_v,
	sql_mediumint_unsigned, mediumint_unsigned_v,
	sql_bigint,				bigint_v,
	sql_bigint_unsigned,	bigint_unsigned_v,

	sql_float,				float_v,





	sql_double,				double_v,
	sql_decimal,			decimal_v,

	sql_bool,				bool_v,






	sql_date,				date_v,
	sql_time,				time_v,
	sql_datetime,			datetime_v,
	sql_char,				char_v,	// only need one stringish type...
	sql_blob,				blob_v)	// ...and one blob type; they're all
									// the same under the hood in MySQL++

int
main()
{
	Query q(0);		// don't pass 0 for conn parameter in real code
	test empty(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, false,
			Date(), Time(), DateTime(), "", sql_blob());
	test filled(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11.0, 12.0, 13.0,
			bool(14), Date("1515-15-15"), Time("16:16:16"),
			DateTime("1717-17-17 17:17:17"), "18", sql_blob("1\09", 3));



	cout << q.insert(empty) << endl << endl;
	cout << q.insert(filled) << endl << endl;
	cout << q.replace(empty) << endl << endl;
	cout << q.replace(filled) << endl << endl;
	cout << q.update(filled, empty) << endl << endl;

	return 0;
}

Changes to test/cpool.cpp.

1
2
3

4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27



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
56
57
58
59
60
61
62
63
64
65




66
67





68































































69



70
71
















72
73






















74
75































76

77



78


79




80









































































































81
82





































































































83



84
85






86
87






88
89
















90
91















92





93
94












95










96
97











































98




99


100
















101
102
103



















































104
105












/***********************************************************************
 test/cpool.cpp - Tests the ConnectionPool class.


 Copyright (c) 2007-2008 by Educational Technology Resources, Inc. and
 (c) 2007 by Jonathan Wakely.  Others may also hold copyrights on
 code in this file.  See the CREDITS.txt file in the top directory of
 the distribution for details.

 This file is part of MySQL++.

 MySQL++ is free software; you can redistribute it and/or modify it
 under the terms of the GNU Lesser General Public License as published
 by the Free Software Foundation; either version 2.1 of the License, or
 (at your option) any later version.

 MySQL++ is distributed in the hope that it will be useful, but WITHOUT
 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
 License for more details.

 You should have received a copy of the GNU Lesser General Public
 License along with MySQL++; if not, write to the Free Software
 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
 USA
***********************************************************************/

#include <cpool.h>



#include <connection.h>


#include <iostream>







#if defined(MYSQLPP_PLATFORM_WINDOWS)
#	define SLEEP(n) Sleep((n) * 1000)


#else









#	include <unistd.h>





#	define SLEEP(n) sleep(n)












#endif


using namespace std;



class TestConnection : public mysqlpp::Connection
{
public:
	TestConnection() : itime_(time(0)) { }
	time_t instantiation_time() const { return itime_; }

private:
	time_t itime_;
};


class TestConnectionPool : public mysqlpp::ConnectionPool
{
public:
	~TestConnectionPool() { clear(); }

	unsigned int max_idle_time() { return 1; }

private:
	TestConnection* create() { return new TestConnection; }
	void destroy(mysqlpp::Connection* cp) { delete cp; }
};


int




main()
{





	TestConnectionPool pool;



































































	mysqlpp::Connection* conn1 = pool.grab();
	mysqlpp::Connection* conn2 = pool.grab();
















	if (conn1 == conn2) {
		cerr << "Pool returned the same connection twice!" << endl;






















		return 1;
	}

































	pool.release(conn2);



	mysqlpp::Connection* conn3 = pool.grab();


	if (conn2 != conn3) {




		cerr << "conn2 should have been reused but wasn't!" << endl;









































































































		return 1;
	}









































































































	time_t itime_c1 = dynamic_cast<TestConnection*>(conn1)->
			instantiation_time();






	pool.release(conn1);
	SLEEP(pool.max_idle_time() + 1);






	mysqlpp::Connection* conn4 = pool.grab();
	time_t itime_c4 = dynamic_cast<TestConnection*>(conn4)->
















			instantiation_time();
	if (itime_c1 == itime_c4) {















		cerr << "conn1 should have been destroyed but wasn't!" << endl;





		return 1;
	}























	pool.release(conn3);
	pool.release(conn4);











































	pool.shrink();




	if (!pool.empty()) {


		cerr << "Shrunken pool is not empty!" << endl;
















		return 1;
	}




















































	return 0;
}













|

>
|
<
|
|



















|
>
>
>
|

>
|
>
>
>
>
>

>
|
<
>
>

>
>
>
>
>
>
>
>
>
|
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>

>
|
|
>

>
|
|
<
<
<
|
|
<
<
|

<
|
|
|
|
|
|
<
<
<
<



>
>
>
>
|
|
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
>
>
|
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|

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

>
|
>
>
>
|
>
>
|
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|

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

>
>
>
|
|
>
>
>
>
>
>
|
|
>
>
>
>
>
>
|
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
>
>
>
>
|

>
>
>
>
>
>
>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
|
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
>
>
>
|
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
|

>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
|
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5

6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
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
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82



83
84


85
86

87
88
89
90
91
92




93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
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
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
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
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
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
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
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
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
/***********************************************************************
 query.cpp - Implements the Query class.

 Copyright (c) 1998 by Kevin Atkinson, (c) 1999-2001 by MySQL AB, and
 (c) 2004-2009 by Educational Technology Resources, Inc.  Others may

 also hold copyrights on code in this file.  See the CREDITS.txt file
 in the top directory of the distribution for details.

 This file is part of MySQL++.

 MySQL++ is free software; you can redistribute it and/or modify it
 under the terms of the GNU Lesser General Public License as published
 by the Free Software Foundation; either version 2.1 of the License, or
 (at your option) any later version.

 MySQL++ is distributed in the hope that it will be useful, but WITHOUT
 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
 License for more details.

 You should have received a copy of the GNU Lesser General Public
 License along with MySQL++; if not, write to the Free Software
 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
 USA
***********************************************************************/

#include "query.h"

#include "autoflag.h"
#include "dbdriver.h"
#include "connection.h"

namespace mysqlpp {

// Force insertfrom() policy template instantiation.  Required to make 
// VC++ happy.
Query::RowCountInsertPolicy<Transaction> RowCountInsertPolicyI(0);
Query::SizeThresholdInsertPolicy<Transaction> SizeThresholdInsertPolicyI(0);
Query::MaxPacketInsertPolicy<Transaction> MaxPacketInsertPolicyI(0);

Query::Query(Connection* c, bool te, const char* qstr) :
#if defined(MYSQLPP_HAVE_STD__NOINIT)

// prevents a double-init memory leak in native VC++ RTL (not STLport!)
std::ostream(std::_Noinit),
#else
std::ostream(0),
#endif
OptionalExceptions(te),
template_defaults(this),
conn_(c),
copacetic_(true)
{
	// Set up our internal IOStreams string buffer
	init(&sbuffer_);

	// Insert passed query string into our string buffer, if given
	if (qstr) {
		sbuffer_.str(qstr);
		seekp(0, std::ios::end);	// allow more insertions at end
	} 

	// Override any global locale setting; we want to use the classic C
	// locale so we don't get weird things like thousands separators in
	// integers inserted into the query stream.
	imbue(std::locale::classic());
}

Query::Query(const Query& q) :
#if defined(MYSQLPP_HAVE_STD__NOINIT)
// ditto above
std::ostream(std::_Noinit),
#else
std::ostream(0),
#endif
OptionalExceptions(q.throw_exceptions())
{
	// Set up our internal IOStreams string buffer
	init(&sbuffer_);

	// See above for reason we override locale for Query streams.
	imbue(std::locale::classic());




	// Copy the other query as best we can
	operator =(q);


}



ulonglong
Query::affected_rows()
{
	return conn_->driver()->affected_rows();
}






int
Query::errnum() const
{
	return conn_->errnum();
}


const char*
Query::error() const
{
	return conn_->error();
}


size_t
Query::escape_string(std::string* ps, const char* original,
		size_t length) const
{
	if (conn_ && *conn_) {
		// Normal case
		return conn_->driver()->escape_string(ps, original, length);
	}
	else {
		// Should only happen in test/test_manip.cpp, since it doesn't
		// want to open a DB connection just to test the manipulators.
		return DBDriver::escape_string_no_conn(ps, original, length);
	}
}


size_t
Query::escape_string(char* escaped, const char* original,
		size_t length) const
{
	if (conn_ && *conn_) {
		// Normal case
		return conn_->driver()->escape_string(escaped, original, length);
	}
	else {
		// Should only happen in test/test_manip.cpp, since it doesn't
		// want to open a DB connection just to test the manipulators.
		return DBDriver::escape_string_no_conn(escaped, original, length);
	}
}


bool
Query::exec(const std::string& str)
{
	if ((copacetic_ = conn_->driver()->execute(str.data(),
			static_cast<unsigned long>(str.length()))) == true) {
		if (parse_elems_.size() == 0) {
			// Not a template query, so auto-reset
			reset();
		}
		return true;
	}
	else if (throw_exceptions()) {
		throw BadQuery(error(), errnum());
	}
	else {
		return false;
	}
}


SimpleResult 
Query::execute() 
{ 
	AutoFlag<> af(template_defaults.processing_);
	return execute(str(template_defaults)); 
}


SimpleResult
Query::execute(SQLQueryParms& p)
{
	AutoFlag<> af(template_defaults.processing_);
	return execute(str(p));
}


SimpleResult
Query::execute(const SQLTypeAdapter& s)
{
	if (!parse_elems_.empty() && !template_defaults.processing_) {
		// We're a template query and this isn't a recursive call, so
		// take s to be a lone parameter for the query.  We will come
		// back in here with a completed query, but the processing_
		// flag will be set, allowing us to avoid an infinite loop.
		AutoFlag<> af(template_defaults.processing_);
		return execute(SQLQueryParms() << s);
	}
	else {
		// Take s to be the entire query string
		return execute(s.data(), s.length());
	}
}


SimpleResult
Query::execute(const char* str, size_t len)
{
	if (!parse_elems_.empty() && !template_defaults.processing_) {
		// We're a template query and this isn't a recursive call, so
		// take s to be a lone parameter for the query.  We will come
		// back in here with a completed query, but the processing_
		// flag will be set, allowing us to avoid an infinite loop.
		AutoFlag<> af(template_defaults.processing_);
		return execute(SQLQueryParms() << str << len );
	}
	if ((copacetic_ = conn_->driver()->execute(str, len)) == true) {
		if (parse_elems_.size() == 0) {
			// Not a template query, so auto-reset
			reset();
		}
		return SimpleResult(conn_, insert_id(), affected_rows(), info());
	}
	else if (throw_exceptions()) {
		throw BadQuery(error(), errnum());
	}
	else {
		return SimpleResult();
	}
}


std::string
Query::info()
{
	return conn_->driver()->query_info();
}


ulonglong
Query::insert_id()
{
	return conn_->driver()->insert_id();
}


bool
Query::more_results()
{
	return conn_->driver()->more_results();
}


Query&
Query::operator=(const Query& rhs)
{
	set_exceptions(rhs.throw_exceptions());
	template_defaults = rhs.template_defaults;
	conn_ = rhs.conn_;
	copacetic_ = rhs.copacetic_;

	*this << rhs.sbuffer_.str();

	parse_elems_  = rhs.parse_elems_;
	parsed_names_ = rhs.parsed_names_;
	parsed_nums_  = rhs.parsed_nums_;

	return *this;
}

Query::operator void*() const
{
	return *conn_ && copacetic_ ? const_cast<Query*>(this) : 0;
}


void
Query::parse()
{
	std::string str = "";
	char num[4];
	std::string name;

	char* s = new char[sbuffer_.str().size() + 1];
	memcpy(s, sbuffer_.str().data(), sbuffer_.str().size());
	s[sbuffer_.str().size()] = '\0';
	const char* s0 = s;

	while (*s) {
		if (*s == '%') {
			// Following might be a template parameter declaration...
			s++;
			if (*s == '%') {
				// Doubled percent sign, so insert literal percent sign.
				str += *s++;
			}
			else if (isdigit(*s)) {
				// Number following percent sign, so it signifies a
				// positional parameter.  First step: find position
				// value, up to 3 digits long.
				num[0] = *s;
				s++;
				if (isdigit(*s)) {
					num[1] = *s;
					num[2] = 0;
					s++;
					if (isdigit(*s)) {
						num[2] = *s;
						num[3] = 0;
						s++;
					}
					else {
						num[2] = 0;
					}
				}
				else {
					num[1] = 0;
				}
				signed char n = atoi(num);

				// Look for option character following position value.
				char option = ' ';
				if (*s == 'q' || *s == 'Q') {
					option = *s++;
				}

				// Is it a named parameter?
				if (*s == ':') {
					// Save all alphanumeric and underscore characters
					// following colon as parameter name.
					s++;
					for (/* */; isalnum(*s) || *s == '_'; ++s) {
						name += *s;
					}

					// Eat trailing colon, if it's present.
					if (*s == ':') {
						s++;
					}

					// Update maps that translate parameter name to
					// number and vice versa.
					if (n >= static_cast<short>(parsed_names_.size())) {
						parsed_names_.insert(parsed_names_.end(),
								static_cast<std::vector<std::string>::size_type>(
										n + 1) - parsed_names_.size(),
								std::string());
					}
					parsed_names_[n] = name;
					parsed_nums_[name] = n;
				}

				// Finished parsing parameter; save it.
				parse_elems_.push_back(SQLParseElement(str, option, n));
				str = "";
				name = "";
			}
			else {
				// Insert literal percent sign, because sign didn't
				// precede a valid parameter string; this allows users
				// to play a little fast and loose with the rules,
				// avoiding a double percent sign here.
				str += '%';
			}
		}
		else {
			// Regular character, so just copy it.
			str += *s++;
		}
	}

	parse_elems_.push_back(SQLParseElement(str, ' ', -1));
	delete[] s0;
}


SQLTypeAdapter*
Query::pprepare(char option, SQLTypeAdapter& S, bool replace)
{
	if (S.is_processed()) {
		return &S;
	}

	if (option == 'q') {
		std::string temp(S.quote_q() ? "'" : "", S.quote_q() ? 1 : 0);

		if (S.escape_q()) {
			char *escaped = new char[S.size() * 2 + 1];
			size_t len = conn_->driver()->escape_string(escaped,
					S.data(), static_cast<unsigned long>(S.size()));
			temp.append(escaped, len);
			delete[] escaped;
		}
		else {
			temp.append(S.data(), S.length());
		}

		if (S.quote_q()) temp.append("'", 1);

		SQLTypeAdapter* ss = new SQLTypeAdapter(temp);

		if (replace) {
			S = *ss;
			S.set_processed();
			delete ss;
			return &S;
		}
		else {
			return ss;
		}
	}
	else if (option == 'Q' && S.quote_q()) {
		std::string temp("'", 1);
		temp.append(S.data(), S.length());
		temp.append("'", 1);
		SQLTypeAdapter *ss = new SQLTypeAdapter(temp);

		if (replace) {
			S = *ss;
			S.set_processed();
			delete ss;
			return &S;
		}
		else {
			return ss;
		}
	}
	else {
		if (replace) {
			S.set_processed();
		}
		return &S;
	}
}


void
Query::proc(SQLQueryParms& p)
{
	sbuffer_.str("");

	for (std::vector<SQLParseElement>::iterator i = parse_elems_.begin();
			i != parse_elems_.end(); ++i) {
		MYSQLPP_QUERY_THISPTR << i->before;
		int num = i->num;
		if (num >= 0) {
			SQLQueryParms* c;
			if (size_t(num) < p.size()) {
				c = &p;
			}
			else if (size_t(num) < template_defaults.size()) {
				c = &template_defaults;
			}
			else {
				*this << " ERROR";
				throw BadParamCount(
						"Not enough parameters to fill the template.");
			}

			SQLTypeAdapter& param = (*c)[num];
			if (param.is_null()) {
				MYSQLPP_QUERY_THISPTR << "NULL";
			}
			else {
				SQLTypeAdapter* ss = pprepare(i->option, param, c->bound());
				MYSQLPP_QUERY_THISPTR << *ss;
				if (ss != &param) {
					// pprepare() returned a new string object instead of
					// updating param in place, so we need to delete it.
					delete ss;
				}
			}
		}
	}
}


void
Query::reset()
{
	seekp(0);
	clear();
	sbuffer_.str("");

	parse_elems_.clear();
	template_defaults.clear();
}


StoreQueryResult 
Query::store() 
{ 
	AutoFlag<> af(template_defaults.processing_);
	return store(str(template_defaults)); 
}


StoreQueryResult
Query::store(SQLQueryParms& p)
{
	AutoFlag<> af(template_defaults.processing_);
	return store(str(p));
}


StoreQueryResult
Query::store(const SQLTypeAdapter& s)
{
	if (!parse_elems_.empty() && !template_defaults.processing_) {
		// We're a template query and this isn't a recursive call, so
		// take s to be a lone parameter for the query.  We will come
		// back in here with a completed query, but the processing_
		// flag will be set, allowing us to avoid an infinite loop.
		AutoFlag<> af(template_defaults.processing_);
		return store(SQLQueryParms() << s);
	}
	else {
		// Take s to be the entire query string
		return store(s.data(), s.length());
	}
}


StoreQueryResult
Query::store(const char* str, size_t len)
{
	if (!parse_elems_.empty() && !template_defaults.processing_) {
		// We're a template query and this isn't a recursive call, so
		// take s to be a lone parameter for the query.  We will come
		// back in here with a completed query, but the processing_
		// flag will be set, allowing us to avoid an infinite loop.
		AutoFlag<> af(template_defaults.processing_);
		return store(SQLQueryParms() << str << len );
	}
	MYSQL_RES* res = 0;
	if ((copacetic_ = conn_->driver()->execute(str, len)) == true) {
		res = conn_->driver()->store_result();
	}

	if (res) {
		if (parse_elems_.size() == 0) {
			// Not a template query, so auto-reset
			reset();
		}
		return StoreQueryResult(res, conn_->driver(), throw_exceptions());
	}
	else {
		// Either result set is empty, or there was a problem executing
		// the query or storing its results.  Since it's not an error to
		// use store() with queries that never return results (INSERT,
		// DELETE, CREATE, ALTER...) we need to figure out which case
		// this is.  (You might use store() instead of execute() for
		// such queries when the query strings come from "outside".)
		copacetic_ = (conn_->errnum() == 0);
		if (copacetic_) {
			if (parse_elems_.size() == 0) {
				// Not a template query, so auto-reset
				reset();
			}
			return StoreQueryResult();
		}
		else if (throw_exceptions()) {
			throw BadQuery(error(), errnum());
		}
		else {
			return StoreQueryResult();
		}
	}
}


StoreQueryResult
Query::store_next()
{
#if MYSQL_VERSION_ID > 41000		// only in MySQL v4.1 +
	DBDriver::nr_code rc = conn_->driver()->next_result();
	if (rc == DBDriver::nr_more_results) {
		// There are more results, so return next result set.
		MYSQL_RES* res = conn_->driver()->store_result();
		if (res) {
			return StoreQueryResult(res, conn_->driver(),
					throw_exceptions());
		}
		else {
			// Result set is null, but throw an exception only i it is
			// null because of some error.  If not, it's just an empty
			// result set, which is harmless.  We return an empty result
			// set if exceptions are disabled, as well.
			if (conn_->errnum() && throw_exceptions()) {
				throw BadQuery(error(), errnum());
			}
			else {
				return StoreQueryResult();
			}
		}
	}
	else if (throw_exceptions()) {
		if (rc == DBDriver::nr_error) {
			throw BadQuery(error(), errnum());
		}
		else if (conn_->errnum()) {
			throw BadQuery(error(), errnum());
		}
		else {
			return StoreQueryResult();	// normal end-of-result-sets case
		}
	}
	else {
		return StoreQueryResult();
	}
#else
	return store();
#endif // MySQL v4.1+
}


std::string
Query::str(SQLQueryParms& p)
{
	if (!parse_elems_.empty()) {
		proc(p);
	}

	return sbuffer_.str();
}


UseQueryResult 
Query::use() 
{ 
	AutoFlag<> af(template_defaults.processing_);
	return use(str(template_defaults)); 
}


UseQueryResult
Query::use(SQLQueryParms& p)
{
	AutoFlag<> af(template_defaults.processing_);
	return use(str(p));
}


UseQueryResult
Query::use(const SQLTypeAdapter& s)
{
	if (!parse_elems_.empty()  && !template_defaults.processing_) {
		// We're a template query and this isn't a recursive call, so
		// take s to be a lone parameter for the query.  We will come
		// back in here with a completed query, but the processing_
		// flag will be set, allowing us to avoid an infinite loop.
		AutoFlag<> af(template_defaults.processing_);
		return use(SQLQueryParms() << s);
	}
	else {
		// Take s to be the entire query string
		return use(s.data(), s.length());
	}
}


UseQueryResult
Query::use(const char* str, size_t len)
{
	if (!parse_elems_.empty() && !template_defaults.processing_) {
		// We're a template query and this isn't a recursive call, so
		// take s to be a lone parameter for the query.  We will come
		// back in here with a completed query, but the processing_
		// flag will be set, allowing us to avoid an infinite loop.
		AutoFlag<> af(template_defaults.processing_);
		return use(SQLQueryParms() << str << len );
	}
	MYSQL_RES* res = 0;
	if ((copacetic_ = conn_->driver()->execute(str, len)) == true) {
		res = conn_->driver()->use_result();
	}

	if (res) {
		if (parse_elems_.size() == 0) {
			// Not a template query, so auto-reset
			reset();
		}
		return UseQueryResult(res, conn_->driver(), throw_exceptions());
	}
	else {
		// See comments in store() above for why we distinguish between
		// empty result sets and actual error returns here.
		copacetic_ = (conn_->errnum() == 0);
		if (copacetic_) {
			if (parse_elems_.size() == 0) {
				// Not a template query, so auto-reset
				reset();
			}
			return UseQueryResult();
		}
		else if (throw_exceptions()) {
			throw BadQuery(error(), errnum());
		}
		else {
			return UseQueryResult();
		}
	}
}


} // end namespace mysqlpp

Changes to test/datetime.cpp.

1
2
3

4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
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
56


57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73



74
75
76
77


78


79
80
81
82
83

84
85
86
87
88
89

90
91
92
93
94
95
96
97

98



99

100
101
102

103
104
105
106
107
108
109
110
111
112
113
114
115



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

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
191
192
193

194
195
196


197

198
199


200



201
202
203

204
205
206
207
208
209
210
211
212
213
214
215
216
217

218
/***********************************************************************
 test/datetime.cpp - Tests the Date, DateTime, and Time classes.


 Copyright (c) 2007-2008 by Educational Technology Resources, Inc.
 Others may also hold copyrights on code in this file.  See the
 CREDITS.txt file in the top directory of the distribution for details.

 This file is part of MySQL++.

 MySQL++ is free software; you can redistribute it and/or modify it
 under the terms of the GNU Lesser General Public License as published
 by the Free Software Foundation; either version 2.1 of the License, or
 (at your option) any later version.

 MySQL++ is distributed in the hope that it will be useful, but WITHOUT
 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
 License for more details.

 You should have received a copy of the GNU Lesser General Public
 License along with MySQL++; if not, write to the Free Software
 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
 USA
***********************************************************************/

#include <mysql++.h>

#include <iostream>
#include <sstream>
#include <string>

#include <stdio.h>

using namespace mysqlpp;
using namespace std;


// Compare the given string against the object inserted into a Query stream.
template <class T>
static unsigned int
test_query_insert(const T& object, const char* expected,
		const char* what)

{
	Query q = Connection().query();	// don't do this in real code
	q << object;
	if (q.str().compare(expected) == 0) {
		cout << what << " is '" << expected <<
				"' in Query, as expected." << endl;
		return 0;










	}



	else {
		cerr << what << " '" << object << "' should be '" <<
				expected << "' when inserted into Query!" << endl;
		return 1;
	}
}




// Compare the given string against the object inserted into an ostream.
template <class T>
static unsigned int
test_ostream_insert(const T& object, const char* expected,
		const char* what)
{
	ostringstream os;
	os << object;
	if (os.str().compare(expected) == 0) {
		cout << what << " is '" << expected <<
				"' in ostream, as expected." << endl;
		return 0;
	}
	else {
		cerr << what << " '" << object << "' should be '" <<



				expected << "' when inserted into ostream!" << endl;
		return 1;
	}
}






// Compare the given string against the return value of the object's
// str() method.
template <class T>
static unsigned int

test_str_method(const T& object, const char* expected, const char* what)
{
	if (object.str().compare(expected) == 0) {
		cout << what << ".str() returns '" << expected <<
				"', as expected." << endl;
		return 0;

	}
	else {
		cerr << what << " '" << object << "' should return '" <<
				expected << "' from str() method!" << endl;
		return 1;
	}
}






// Compare the given string against the object when cast to std::string

template <class T>
static unsigned int
test_string_operator(const T& object, const char* expected,

		const char* what)
{
	if (string(object).compare(expected) == 0) {
		cout << "string(" << what << ") is '" << expected <<
				"', as expected." << endl;
		return 0;
	}
	else {
		cerr << what << " '" << object << "' should be '" <<
				expected << "' when cast to std::string!" << endl;
		return 1;
	}
}






// Compare the given string against the object when converted in several
// different ways to a string.
template <class T>
static unsigned int
test_stringization(const T& object, const char* expected,
		const char* what)


{
	return	test_query_insert(object, expected, what) +
			test_ostream_insert(object, expected, what) +
			test_string_operator(object, expected, what) +
			test_str_method(object, expected, what);
}


// Given a Date and a set of values we should expect to be in it,
// compare its outputs against values we compute separately.
static unsigned int
test_date(const Date& d, int year, int month, int day)
{
	if (	d.year() == year &&
			d.month() == month &&
			d.day() == day) {
		char ac[20];
		snprintf(ac, sizeof(ac), "%04d-%02d-%02d",
				year, month, day);
		return test_stringization(d, ac, "Date");

	}
	else {
		cerr << "Date '" << d << "' values should be '" <<
				year << '-' << month << '-' << day << endl;
		return 1;
	}









}


// Given a Time and a set of values we should expect to be in it,
// compare its outputs against values we compute separately.
static unsigned int


test_time(const Time& t, int hour, int minute, int second)
{
	if (	t.hour() == hour &&
			t.minute() == minute &&
			t.second() == second) {
		char ac[20];
		snprintf(ac, sizeof(ac), "%02d:%02d:%02d",
				hour, minute, second);


		return test_stringization(t, ac, "Time");

	}
	else {
		cerr << "Time '" << t << "' values should be '" <<
				hour << ':' << minute << ':' << second << endl;
		return 1;
	}










}


// Given a DateTime and a set of values we should expect to be in it,
// compare its outputs against values we compute separately.
static unsigned int
test_datetime(const DateTime& dt,
		int year, int month, int day,
		int hour, int minute, int second)
{

	return	test_date(Date(dt), year, month, day) +
			test_time(Time(dt), hour, minute, second);
}






// Run tests above for the various types we support using the date and
// time values given.
static unsigned int
test(int year, int month, int day, int hour, int minute, int second)
{
	unsigned int failures = 0;
	failures += test_date(Date(year, month, day), year, month, day);
	failures += test_datetime(

			DateTime(year, month, day, hour, minute, second),
			year, month, day, hour, minute, second);
	failures += test_time(Time(hour, minute, second), hour, minute,


			second);

	return failures;
}







int
main()

{
	unsigned int failures = 0;
#if !defined(__SUNPRO_CC)
	// Sun CC can't compile these tests for some reason.  So, skip them.
	// See http://lists.mysql.com/plusplus/8164
	failures += test(0, 0, 0, 0, 0, 0);
	failures += test(1, 2, 3, 4, 5, 6);
	failures += test_stringization(DateTime(), "NOW()", "DateTime");
	DateTime dt;
	dt.year(2007);
	failures += test_stringization(dt, "2007-00-00 00:00:00", "DateTime");
#endif
	return failures;
}



|

>
|
|
|



















|

<
<
|

<

|
<

|
<
<
|
<
|
>

<
<
|
<
<
|
>
>
>
>
>
>
>
>
>
>
|
>
>
>
|
|
<
<
|
|
>
>
|
|
|
|
<
|
|

<
<
|
<
<
|


<
>
>
>
<
<
|
|
>
>
|
>
>
|
|
|
|
<
>
|

<
<
<
|
>
|
<
<
<
<
|
|
|
>
|
>
>
>
|
>
|
<
<
>
|

<
<
<
|
|
<
<
<
<
|
|
>
>
>
|
>
|
<
<
<
<
|
|
>
>

|
<
<
|



|
<
<
|

<
<
<
<
<
<
|
>
|
|
<
<
<
|
>
>
>
>
>
>
>
>
>



|
<
<
>
>
|

<
<
<
<
<
|
>
>
|
>
|
|
<
<
<
|
>
>
>
>
>
>
>
>
>
>



<
<
|
|
<
<

>
|
<
|
>
>
|
>
>
|
<
<
<
<
<
<
<
<
>
|
|
|
>
>
|
>
|
|
>
>
|
>
>
>
|
<
<
>
|
<
<
<
<
<
<
<
<
<
<
<
<
|
>

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
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
56


57
58
59
60
61
62
63
64

65
66
67


68


69
70
71

72
73
74


75
76
77
78
79
80
81
82
83
84
85

86
87
88



89
90
91




92
93
94
95
96
97
98
99
100
101
102


103
104
105



106
107




108
109
110
111
112
113
114
115




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
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
191
192
193
194
195
196
197
198
199
200


201
202












203
204
205
/***********************************************************************
 row.cpp - Implements the Row class.

 Copyright (c) 1998 by Kevin Atkinson, (c) 1999-2001 by MySQL AB, and
 (c) 2004-2007 by Educational Technology Resources, Inc.  Others may
 also hold copyrights on code in this file.  See the CREDITS.txt file
 in the top directory of the distribution for details.

 This file is part of MySQL++.

 MySQL++ is free software; you can redistribute it and/or modify it
 under the terms of the GNU Lesser General Public License as published
 by the Free Software Foundation; either version 2.1 of the License, or
 (at your option) any later version.

 MySQL++ is distributed in the hope that it will be useful, but WITHOUT
 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
 License for more details.

 You should have received a copy of the GNU Lesser General Public
 License along with MySQL++; if not, write to the Free Software
 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
 USA
***********************************************************************/

#include "row.h"



#include "result.h"



namespace mysqlpp {


Row::Row(MYSQL_ROW row, const ResultBase* res,


		const unsigned long* lengths, bool throw_exceptions) :

OptionalExceptions(throw_exceptions),
initialized_(false)
{


	if (row) {


		if (res) {
			size_type size = res->num_fields();
			data_.reserve(size);
			for (size_type i = 0; i < size; ++i) {
				bool is_null = row[i] == 0;
				data_.push_back(value_type(
						is_null ? "NULL" : row[i],
						is_null ? 4 : lengths[i],
						res->field_type(int(i)),
						is_null));
			}

			field_names_ = res->field_names();
			initialized_ = true;
		}
		else if (throw_exceptions) {
			throw ObjectNotInitialized("RES is NULL");


		}
	}
	else if (throw_exceptions) {
		throw ObjectNotInitialized("ROW is NULL");
	}
}



Row::const_reference
Row::at(size_type i) const
{


	if (i < size()) {


		return data_[i];
	}
	else {

		throw BadIndex("Row", int(i), int(size()));
	}
}




equal_list_ba<FieldNames, Row, quote_type0>
Row::equal_list(const char* d, const char* e) const
{
	return equal_list_ba<FieldNames, Row, quote_type0>(
			*field_names_, *this, d, e, quote);
}


template <class Manip>

equal_list_ba<FieldNames, Row, Manip>
Row::equal_list(const char* d, const char* e, Manip m) const
{



	return equal_list_ba<FieldNames, Row, Manip>(
			*field_names_, *this, d, e, m);
}






value_list_ba<FieldNames, do_nothing_type0>
Row::field_list(const char* d) const
{
	return value_list_ba<FieldNames, do_nothing_type0>
			(*field_names_, d, do_nothing);
}


template <class Manip>


value_list_ba<FieldNames, Manip>
Row::field_list(const char *d, Manip m) const
{



	return value_list_ba<FieldNames, Manip>(*field_names_, d, m);
}






template <class Manip>
value_list_b<FieldNames, Manip>
Row::field_list(const char *d, Manip m, const std::vector<bool>& vb) const
{
	return value_list_b<FieldNames, Manip>(*field_names_, vb, d, m);
}






value_list_b<FieldNames, quote_type0>
Row::field_list(const char* d, const std::vector<bool>& vb) const
{
	return value_list_b<FieldNames, quote_type0>(*field_names_,


			vb, d, quote);
}


value_list_b<FieldNames, quote_type0>


Row::field_list(const std::vector<bool>& vb) const
{






	return value_list_b<FieldNames, quote_type0>(*field_names_,
			vb, ",", quote);
}





template <class Manip> value_list_b<FieldNames, Manip>
Row::field_list(const char* d, Manip m, bool t0, bool t1, bool t2,
		bool t3, bool t4, bool t5, bool t6, bool t7, bool t8, bool t9,
		bool ta, bool tb, bool tc) const
{
	std::vector<bool> vb;
	create_vector(field_names_->size(), vb, t0, t1, t2, t3, t4,
			t5, t6, t7, t8, t9, ta, tb, tc);
	return value_list_b<FieldNames, Manip>(*field_names_, vb, d, m);
}


value_list_b<FieldNames, quote_type0>


Row::field_list(const char *d, bool t0, bool t1, bool t2, bool t3,
		bool t4, bool t5, bool t6, bool t7, bool t8, bool t9, bool ta,
		bool tb, bool tc) const
{





	std::vector<bool> vb;
	create_vector(field_names_->size(), vb, t0, t1, t2, t3, t4,
			t5, t6, t7, t8, t9, ta, tb, tc);
	return value_list_b<FieldNames, quote_type0>(*field_names_,
			vb, d, quote);
}





value_list_b<FieldNames, quote_type0>
Row::field_list(bool t0, bool t1, bool t2, bool t3, bool t4, bool t5,
		bool t6, bool t7, bool t8, bool t9, bool ta, bool tb,
		bool tc) const
{
	std::vector<bool> vb;
	create_vector(field_names_->size(), vb, t0, t1, t2, t3, t4,
			t5, t6, t7, t8, t9, ta, tb, tc);
	return value_list_b<FieldNames, quote_type0>(*field_names_,
			vb, ",", quote);
}




Row::size_type
Row::field_num(const char* name) const


{
	if (field_names_) {
		return (*field_names_)[name];

	}
	else if (throw_exceptions()) {
		throw BadFieldName(name);
	}
	else {
		return 0;
	}








}


const Row::value_type&
Row::operator [](const char* field) const
{
	size_type si = field_num(field);
	if (si < size()) {
		return at(si);
	}
	else if (throw_exceptions()) {
		throw BadFieldName(field);
	}
	else {
		static value_type empty;
		return empty;
	}


}














} // end namespace mysqlpp

Changes to test/insertpolicy.cpp.


1


2



3

























































































4


5





6




7

















































































8



9





























































































10



11





12






13


14












































































15

16
17

18

19


























































































































































































20



21



22



23





24

25















































































26





27























































































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











































































56

57





58



59






60













































































































































































61





62

63


64











65









66
































































67
































































































68






69



70





















































































71


72


73


74

























































































75


76




77


78



















































































79

80

81

82





























































































83


84


85



86





















































































































































































87




88


89


90
91

















































































































































































































































































































































































































92

93














































94
95

96














97




98

99




100

101





102

103








104







































































105

/***********************************************************************


 test/insertpolicy.cpp - Checks that the *InsertPolicy objects work



 	as expected.




























































































 Copyright (c) 2009 by Educational Technology Resources, Inc.





 Others may also hold copyrights on code in this file.  See the




 CREDITS.txt file in the top directory of the distribution for details.





















































































 This file is part of MySQL++.

































































































 MySQL++ is free software; you can redistribute it and/or modify it





 under the terms of the GNU Lesser General Public License as published






 by the Free Software Foundation; either version 2.1 of the License, or


 (at your option) any later version.














































































 MySQL++ is distributed in the hope that it will be useful, but WITHOUT
 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or

 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public

 License for more details.






























































































































































































 You should have received a copy of the GNU Lesser General Public



 License along with MySQL++; if not, write to the Free Software



 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301





 USA

***********************************************************************/





















































































#include <mysql++.h>

























































































#include <climits>






#include <iostream>










static const unsigned char nonzero = 4;
























































































































































































































































































template <class InsertPolicy>



static bool








test_policy(InsertPolicy& ip, unsigned char max, bool expected_to_fail)






{

	unsigned char i;






	mysqlpp::Row dummy;

	for (i = 0; i < UCHAR_MAX; ++i) {

		if (!ip.can_add(i, dummy)) {


			break;




		}


	}





















































































































































































































































	if (expected_to_fail ? i != max : i == max) {


		return true;





















































































	}


	else {



		std::cerr << typeid(ip).name() << '(' << int(max) << 


				") allowed " << int(i) << " inserts!" << std::endl;



		return false;



	}




}



















































































template <class InsertPolicy>



static bool






test_policy(InsertPolicy& ip, unsigned char expected_allow_count)













































































































































































{





	return	test_policy(ip, expected_allow_count, false) &&

			test_policy(ip, expected_allow_count + 1, true) &&


			test_policy(ip, expected_allow_count - 1, true) &&











			test_policy(ip, expected_allow_count ? 0 : nonzero, true);









}








































































































































































static bool



test_row_count_nonzero()





















































































{


	mysqlpp::Query::RowCountInsertPolicy<> ip_nonzero(nonzero);


	return test_policy(ip_nonzero, nonzero);


}

































































































static bool


test_row_count_zero()



















































































{

	mysqlpp::Query::RowCountInsertPolicy<> ip_zero(0);

	return test_policy(ip_zero, 0);

}



































































































static bool



test_row_count()





















































































































































































{




	return	test_row_count_nonzero() &&


			test_row_count_zero();


}




















































































































































































































































































































































































































int














































main()
{

	try {














		return test_row_count() ? 0 : 1;




	}

	catch (...) {




		std::cerr << "Unhandled exception caught by "

				"test/insertpolicy!" << std::endl;





		return 2;

	}








}








































































>
|
>
>
|
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

>
>
|
>
>
>
>
>
|
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

>
>
>
|
>
>
>
>
>
|
>
>
>
>
>
>
|
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

>
|
|
>
|
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

>
>
>
|
>
>
>
|
>
>
>
|
>
>
>
>
>
|
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

>
|
>
>
>
>
>
>
|
>
>
>
>
>

>
>
>
>
|
>

>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
>
>
>
>
>
|
>
>
>
|
>
>
>
>
>
>
>
>
|
>
>
>
>
>
>
|
>
|
>
>
>
>
>
>
|
>
|
>
|
>
>
|
>
>
>
>
|
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

>
>
>
|
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
>
|
>
>
>
|
>
>
|
>
>
>
|
>
>
>
|
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

>

>
>
>
>
>
|
>
>
>
|
>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
>
>
>
>
|
>
|
>
>
|
>
>
>
>
>
>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

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

>
>
>
>
>
>
|
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
>
|
>
>
|
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

>
>

>
>
>
>
|
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
|
>
|
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

>
>

>
>
|
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
>
>
>
|
>
>
|
>
>
|

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

>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
|
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
>
>
>
|
>
|
>
>
>
>
|
>
|
>
>
>
>
>
|
>
|
>
>
>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
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
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
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
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
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
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
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
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
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
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
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
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
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
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
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
1694
1695
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
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
1883
1884
1885
1886
1887
1888
1889
1890
1891
1892
1893
1894
1895
1896
1897
1898
1899
1900
1901
1902
1903
1904
1905
1906
1907
1908
1909
1910
1911
1912
1913
1914
1915
1916
1917
1918
1919
1920
1921
1922
1923
1924
1925
1926
1927
1928
1929
1930
1931
1932
1933
1934
1935
1936
1937
1938
1939
1940
1941
1942
1943
1944
1945
1946
1947
1948
1949
1950
1951
1952
1953
1954
1955
1956
1957
1958
1959
1960
1961
1962
1963
1964
1965
1966
1967
1968
1969
1970
1971
1972
1973
1974
1975
1976
1977
1978
1979
1980
1981
1982
1983
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993
1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
2027
2028
2029
2030
2031
2032
2033
2034
2035
2036
2037
2038
2039
2040
2041
2042
2043
2044
2045
2046
2047
2048
2049
2050
2051
2052
2053
2054
2055
2056
2057
2058
2059
2060
2061
2062
2063
2064
2065
2066
2067
2068
2069
2070
2071
2072
2073
2074
2075
2076
2077
2078
2079
2080
2081
2082
2083
2084
2085
2086
2087
2088
2089
2090
2091
2092
2093
2094
2095
2096
2097
2098
2099
2100
2101
2102
2103
2104
2105
2106
2107
2108
2109
2110
2111
2112
2113
2114
2115
2116
2117
2118
2119
2120
2121
2122
2123
2124
2125
2126
2127
2128
2129
2130
2131
2132
2133
2134
2135
2136
2137
2138
2139
2140
2141
2142
2143
2144
2145
2146
2147
2148
2149
2150
2151
2152
2153
2154
2155
2156
2157
2158
2159
2160
2161
2162
2163
2164
2165
2166
2167
2168
2169
2170
2171
2172
2173
2174
2175
2176
2177
2178
2179
2180
2181
2182
2183
2184
2185
2186
2187
2188
2189
2190
2191
2192
2193
2194
2195
2196
2197
2198
2199
2200
2201
2202
2203
2204
2205
2206
2207
2208
2209
2210
2211
2212
2213
2214
2215
2216
2217
2218
2219
2220
2221
2222
2223
2224
2225
2226
2227
2228
2229
2230
2231
2232
2233
2234
2235
2236
2237
2238
2239
2240
2241
2242
2243
2244
2245
2246
2247
2248
2249
2250
2251
2252
2253
2254
2255
2256
2257
2258
2259
2260
2261
2262
2263
2264
2265
2266
2267
2268
2269
2270
2271
2272
2273
2274
2275
2276
2277
2278
2279
2280
2281
2282
2283
2284
2285
2286
2287
2288
2289
2290
2291
2292
2293
2294
2295
2296
2297
2298
2299
2300
2301
2302
2303
2304
2305
2306
2307
2308
2309
2310
2311
2312
2313
2314
2315
2316
2317
2318
2319
2320
2321
2322
2323
2324
2325
2326
2327
2328
2329
2330
2331
2332
2333
2334
2335
2336
2337
2338
2339
2340
2341
2342
2343
2344
2345
2346
2347
2348
2349
2350
2351
2352
2353
2354
2355
2356
2357
2358
2359
2360
2361
2362
2363
2364
2365
2366
2367
2368
2369
2370
2371
2372
2373
2374
2375
2376
2377
2378
2379
2380
2381
2382
2383
2384
2385
2386
2387
2388
2389
2390
2391
2392
2393
2394
2395
2396
2397
2398
2399
2400
2401
2402
2403
2404
2405
2406
2407
2408
2409
2410
2411
2412
2413
2414
2415
2416
2417
2418
2419
2420
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
2475
2476
2477
2478
2479
2480
2481
2482
2483
2484
2485
2486
2487
2488
2489
2490
2491
2492
2493
2494
2495
2496
2497
2498
2499
2500
2501
2502
2503
2504
2505
2506
2507
2508
2509
2510
2511
2512
2513
2514
2515
2516
2517
2518
2519
2520
2521
2522
2523
2524
2525
2526
2527
2528
2529
2530
2531
2532
2533
2534
2535
2536
2537
2538
2539
2540
2541
2542
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
2587
2588
2589
2590
2591
2592
2593
2594
2595
2596
2597
2598
2599
2600
2601
2602
2603
2604
2605
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
2657
2658
2659
2660
2661
2662
2663
2664
2665
2666
2667
2668
2669
2670
2671
2672
2673
2674
2675
2676
2677
2678
2679
2680
2681
2682
2683
2684
2685
2686
2687
2688
2689
2690
2691
2692
2693
2694
2695
2696
2697
2698
2699
2700
2701
2702
2703
2704
2705
2706
2707
2708
2709
2710
2711
2712
2713
2714
2715
2716
2717
2718
2719
2720
2721
2722
2723
2724
2725
2726
2727
2728
2729
2730
2731
2732
2733
2734
2735
2736
2737
2738
2739
2740
2741
2742
2743
2744
2745
2746
2747
2748
2749
2750
2751
2752
2753
2754
2755
2756
2757
2758
2759
2760
2761
2762
2763
2764
2765
2766
2767
2768
2769
2770
2771
2772
2773
2774
2775
2776
2777
2778
2779
2780
2781
2782
2783
2784
2785
2786
2787
2788
2789
2790
2791
2792
2793
2794
2795
2796
2797
2798
2799
2800
2801
2802
2803
2804
2805
2806
2807
2808
2809
2810
2811
2812
2813
2814
2815
2816
2817
2818
2819
2820
2821
2822
2823
2824
2825
2826
2827
2828
2829
2830
2831
2832
2833
2834
2835
2836
2837
2838
2839
2840
2841
2842
2843
2844
2845
2846
2847
2848
2849
2850
2851
2852
2853
2854
2855
2856
2857
2858
2859
2860
2861
2862
2863
2864
2865
2866
2867
2868
2869
2870
2871
2872
2873
2874
2875
2876
2877
2878
2879
2880
2881
2882
2883
2884
2885
2886
2887
2888
2889
2890
2891
2892
2893
2894
2895
2896
2897
2898
2899
2900
2901
2902
2903
2904
2905
2906
2907
2908
2909
2910
2911
2912
2913
2914
2915
2916
2917
2918
2919
2920
2921
2922
2923
2924
2925
2926
2927
2928
2929
2930
2931
2932
2933
2934
2935
2936
2937
2938
2939
2940
2941
2942
2943
2944
2945
2946
2947
2948
2949
2950
2951
2952
2953
2954
2955
2956
2957
2958
2959
2960
2961
2962
2963
2964
2965
2966
2967
2968
2969
2970
2971
2972
2973
2974
2975
2976
2977
2978
2979
2980
2981
2982
2983
2984
2985
2986
2987
2988
2989
2990
2991
2992
2993
2994
2995
2996
2997
2998
2999
3000
3001
3002
3003
3004
3005
3006
3007
3008
3009
3010
3011
3012
3013
3014
3015
3016
3017
3018
3019
3020
3021
3022
3023
3024
3025
3026
3027
3028
3029
3030
3031
3032
3033
3034
3035
3036
3037
3038
3039
3040
3041
3042
3043
3044
3045
3046
3047
3048
3049
3050
3051
3052
3053
3054
3055
3056
3057
3058
3059
3060
3061
3062
3063
3064
3065
3066
3067
3068
3069
3070
3071
3072
3073
3074
3075
3076
3077
3078
3079
3080
3081
3082
3083
3084
3085
3086
3087
3088
3089
3090
3091
3092
3093
3094
3095
3096
3097
3098
3099
3100
3101
3102
3103
3104
3105
3106
3107
3108
3109
3110
3111
3112
3.2.1, 2013.12.10 (r2756)

    o Connection copy ctor wasn't copying the "throw exceptions"
      flag.  The copy always had exceptions enabled.

    o Fixed resetdb's first output message when you run it without
      arguments.  It was giving a misleading message that could
      confuse someone.

    o Previous release tarball was missing a few text files present in
      the source repository.

    o Updated build paths for VC++ and MinGW to track a file layout
      change in Connector/C 6.1.2.


3.2.0, 2013.06.20 (r2747)

    o References to MySQL 5.1 have been replaced with 5.6, that
      being the current GA release.

    o All Windows builds now assume you're using Connector/C 6.1
      instead of having installed the MySQL server on your machine
      just to get development files.  If you are running a MySQL
      server on your development machine and don't want to install
      Connector/C just to make MySQL++ happy, see the README-*.txt
      file for your platform to get instructions on fixing the paths
      so the build system finds the development files under the MySQL
      server directory.

    o The generated VC++ 2008 project files now assume you want 64-bit
      executables.  (It is 2013 now, after all.)

      Since the VC++ 2005 project files continue to be configured for
      32-bit builds, the easiest way to get a 32-bit project in VC++
      2008+ is to import the VC++ *2005* project files, rather than
      adjust the build target settings of all 44 vc2008/*.vcproj
      files within the IDE.

      See README-Visual-C++.txt for more on this change.

    o Added Query::replacefrom(): like insertfrom() but it uses
      REPLACE statements instead of INSERT.  Patch by Adrian Cornish.

    o Added support for SQL "unsigned float" columns.  Patch by
      Leonardo Lang.

    o Added "abicheck" top-level build target, which runs the
      ISPRAS ABI checker tool (http://goo.gl/e19lD) against
      a predecided "ABI-stable" version of MySQL++, comparing it
      against the current version.  This should help avoid future
      unplanned ABI breakages, as happened between 3.0.9 and 3.1.0.

      We have chosen not to revert those changes that broke the ABI,
      but instead have chosen to accept the 3.1.0 ABI as the new
      stable ABI for the rest of the 3.x series.  Running the ABI
      checker is now part of the release process, so we should not
      change the ABI again until 4.0!

    o The Query::insert() and replace() overloads that take a pair
      of iterators now work with containers that only provide forward
      iterators.  Idea by Adrian Cornish.

    o Using libtool again on Autotools systems.  It gives us
      relocatable libraries, which is needed in some linking
      situations.  Patch by Adrian Cornish.

    o VC++ release builds now have optimization enabled.  This might
      also affect other toolchains that create separate Debug and
      Release builds, if Bakefile obeys the directive for those
      systems.  (Such as, perhaps, Xcode.)  Initial patch by Matthew
      Bradbury.

    o Fixed a crash in CommandLine mechanism when the usage message is
      called up for programs that have no "extra" parameter and
      corresponding usage appendage.  Initial patch by "Crazy Pete".

    o Query::storein() now tolerates empty result sets, due either to
      DBMS failure or passing a query that never returns results,
      such as INSERT.

    o Exposed DBDriver::result_empty() as Query::result_empty().  We
      did this primarily because it was needed as a helper for the
      previous fix, but it could also be useful more broadly.

    o Added -Wextra to the pedantic build flags.

    o Fixed the "escape" manipulator so it will work with Null<>
      wrapped types.  Patch by "Kemet".

    o ssqls2parse now depends on libmysqlpp.  (It wasn't getting
      relinked when you changed the library.)

    o The configure script's test for the existence of mysql_ssl_set()
      got broken by a change in the mysql_loc.m4 test, causing it to
      always return "no" even if the platform's MySQL C API library did
      have the function.  Therefore, the SslOption could never be set.
      Fixes this bug: stackoverflow.com/questions/7794408

    o Fixed a missing a "buried headers" ifdef wrapper for
      type_info.cpp.  Patch provided by Xavier Richez.

    o We now export the DBDriver class from the MySQL++ DLL when
      building on Windows.  Client programs can now access it directly,
      instead of being able to access only the fields and members
      exposed through Connection and Query.  Fix suggested by Xavier
      Richez.

    o MinGW builds no longer require that you manually create an import
      library for the MySQL C API DLL from a .def file we provide,
      which would inevitably get outdated.  We can now link directly to
      the DLL, and rely on the MinGW linker to figure out the imports.

    o Split the -l flags out of LDFLAGS in the userman's example
      Makefiles.  They're now in LDLIBS, which causes them to be
      put after -o $(EXE) by the default GNU make rules, where they
      should be.

    o Assorted documentation and build system improvements.

    o Assorted fixes for newer GCCs.


3.1.0, 2010.06.03 (r2670)

    o Default MySQL version now 5.1, having entered GA since 3.0.9.

    o Lots of platform updates tracked, lots of warnings from newer
      compilers squished.  Most by me, some by Adrian Cornish.

    o Added Query::insertfrom(), plus associated classes SQLStream,
      NoTransactions, and the InsertPolicy hierarchy.  Also adds
      examples/ssqls6.cpp, which shows how to use this new feature.
      Thanks for this feature go to Rick Gutleber, except for
      RowCountInsertPolicy, by me.

    o Added comparison operators to tiny_int<T>.  Thanks for this patch
      go to Edward Diener.

    o Added SQLTypeAdapter::is_null().  This lets you retrieve a
      nullable column from the DB, then re-insert a value from that
      column back into the DB via a template query without explicit
      checks for null-ness; it will do the right thing now.

    o Added -f flags to lib/*.pl header file generating scripts to
      allow overriding the default limit of 25 fields for tqueries
      and SSQLSes without having to edit the file, as in previous
      versions of MySQL++.  Also added --with-field-limit option to
      the configure script so you can give both -f options at once
      during the build process.  This latter is especially useful
      for automated binary package builders.

    o The file lib/querydef.h (generated by lib/querydef.pl) now
      defines the MYSQLPP_TQUERY_MAX_PARAMETERS macro, giving the
      maximum number of parameters the functions in the generated file
      allow for template queries.  Similarly, lib/ssqls.h (generated
      by lib/ssqls.pl) defines MYSQLPP_SSQLS_MAX_MEMBERS.

    o Added ConnectionPool::safe_grab(), which pings the grabbed
      connection before returning it.  If the ping fails, we remove
      the dead connection from the pool and try again.  This doesn't
      eliminate the possibility of returning a dead connection;
      there is no protection against race conditions.  It is merely
      a best-effort attempt.

    o Added ConnectionPool::remove(Connection*), which removes a
      connection from the pool.

    o Added ConnectionPool::exchange(), which wraps remove()
      and grab().  It works like a customer support counter in a
      store: "I'm sorry, but this Connection is defective.  Can I
      have another, please?"

    o Added a feature to Transaction, where it can send a SET
      TRANSACTION ISOLATION LEVEL query before it starts the
      transaction proper, affecting the isolation level and the scope
      of that change.

    o Added ScopedConnection class.  Initial version by Joel Fielder,
      lots of changes by me.  Using it instead of explicit safe_grab()
      and release() calls on the pool in examples/cpool.cpp.

    o Added FieldNames::operator[](size_type) overloads.  This is
      necessary to correctly overload the base class versions inherited
      from std::vector.

    o FieldNames wasn't doing field-by-name matches case insentitively,
      most likely since 3.0.0 when we changed it to derive from
      std::vector.  This caused SSQLS (at least) to be case sensitive.
      Fixed this and renamed the stock.sdate field in the SSQLS
      examples to stock.sDate to test this.

    o Added Query::replace(iter, iter), on the model of existing
      insert(iter, iter).  Thanks for this patch go to David Walthour.

    o Added Query::operator!(), overriding basic_ios version so that
      "if (!query)" does the right thing.  Fixes problem report in
      thread http://lists.mysql.com/plusplus/8594

    o Query copy ctor and assignment operator now perform deeper
      copies, so you can pass Query objects around in certain ways
      that used to cause crashes.  Thanks for this patch go to Steven
      Van Ingelgem.

    o Defined *_null variants for every sql_* typedef, wrapping
      all those earlier types in Null<>.  All example programs now use
      these types instead of explicit Null<>-wrapped types.

    o Created a C++ command line parsing mechanism for the examples
      today, and for programs coming in the future.  It uses the
      platform version of getopt() if available, substituting a
      public-domain implementation that gets built into MySQL++
      itself otherwise.  It's documented in the refman -- see
      the CommandLineBase class -- but it's in the newly created
      mysqlpp::internal namespace, which means we don't promise any
      sort of ABI or API stability for it.  You're welcome to use it
      in your own programs, but expect it to change without warning.

    o Added a few missing MYSQLPP_EXPORTs to operator<<()s for stream
      manipulators, to allow their use when MySQL++ is built as a DLL.

    o Added backticks around table and column identifiers in all
      code paths exercised by dtest.  There are some others remaining,
      particularly things like Row::field_list().  Thanks for this
      patch go to Adrian Cornish.

    o Added mysqlpp::NOW() which returns a value that, when inserted
      into a SQL query, results in a call to SQL's NOW() function.
      DateTime::now() -- added in 3.0.0 -- does the same thing,
      but this is shorter and matches the SQL syntax.

    o Calling DBDriver::disconnect() twice no longer calls
      mysql_close() twice.

    o Worked around a weakness on Windows that caused problems in code
      with a connect(), disconnect(), connect() call pattern, when
      also using a named pipe to connect to the DB.  (There never
      has been a problem with this on other platforms or with other
      IPC mechanisms.)

    o Initializing a SQLTypeAdapter with a floating-point value
      equal to infinity or NaN results in SQL null if the type
      is also nullable, or 0 otherwise.  Previously, we got an
      implementation-defined string, which could give invalid SQL,
      or could give 0, a different value from NaN, infinity, or
      SQL null.  This does collapse the notions of NaN and infinity,
      but the MySQL reference manual doesn't say how you're supposed
      to preserve these differences.

    o Removed the dependency of stadapter.h on sql_types.h, just to get
      sql_tinyint*.  #including tinyint.h instead, and using equivalent
      types to what sql_types.h defines.  This is necessary because
      sql_types.h should be one of the last things included from
      mysql++.h, so that it can define sql_* equivalents for everything
      else in MySQL++, which means all those other things need to be
      #included by that point.

    o The "find MySQL++" autoconf macro (config/mysql++.m4) now
      searches for the library in lib64 subdirectories everywhere it
      also looks in lib.  We did this for the C API finder macro way
      back in MySQL++ 2.2.0, and only neglected to do it for this
      macro because it's not used by MySQL++ itself, just provided
      as a courtesy to MySQL++ users that also use autoconf.

    o Also improved the "find C API" macro (config/mysql_loc.m4)
      so it, too, is more useful in third-party projects.

    o Moved private FieldNames::str_to_lwr() method out into its
      own module, in the new mysqlpp::internal namespace, so other
      modules can use it.  Also added an overload for this new global
      method taking std::string instead of char*.

    o userman build process can now find FOP when installed from
      the standard Ubuntu/Debian package repository.

    o No longer generating refman.pdf.  It's difficult to generate
      properly on some platforms, and isn't all that useful anyway
      compared to the HTML version, which builds properly everywhere.

    o Dropped custom.h backwards-compatibility header.  (Deprecated
      over a year ago in MySQL++ 3.0.0.)

    o Fixed a bad pointer access crash in Connection::set_option()
      triggered when the option set call fails.  Thanks for this
      patch go to Kevin Regan.

    o ReconnectOption behavior now knows about a fix in MySQL 5.1.6 and
      newer that lets you set it either before the connection is up,
      or after.  If you try to set this option when MySQL++ is built
      against earlier versions of the MySQL C API, it will refuse to
      set the option because it knows the option will be reset when
      the connection comes up.

    o No longer trying to make the C API library read from a "my"
      options file before connect.  It does that by default, and
      the file is supposed to be .my.cnf anyway.

    o Reworked the load_jpeg example code for clarity, extracting
      load_jpeg_file() routine as an implementation detail and
      making that use the C++ stringstream "slurp into string" idiom
      instead of allocating a C char buffer and copying that into
      a std::string.

    o Restored support for repeating query parameters.  Apparently
      you could say things like "stuff %0 morestuff %0" in v2.1,
      but this was broken by initial 1-parameter fixes in v2.2.
      This patch reportedly lets us have both things at once, and
      improves handling of 1-parameter template queries in general.
      Thanks for this patch go to Martin Gallwey.

    o Added examples/tquery4.cpp based on test code and feedback
      from Martin.

    o Put Comparable class in namespace mysqlpp, where it should always
      have been.  Aside from being just plain wrong, it caused a
      conflict with Boost if you used its Comparable class and hoist
      them both into the global namespace.  Thanks for this patch go
      to Michael Radzewitz.

    o Fixed all the known problems with the Xcode project files.

    o Skeletal support for SSQLS v2.  Doesn't do anything useful
      yet, it just got caught up in the need to release 3.1 as-is.

    o Various enhancements to the test suite.

    o Many, many documentation enhancements.


3.0.9, 2009.02.04 (r2442)

    o It is now possible to use Null<T> objects in const context.

    o Query was emitting thousands separators when used in some
      locales.  Thanks for the fix go to Tomaž Šolc.

    o Restored support for using Query::storein() with template
      queries.  Was mistakenly removed in the 3.0.0 development
      process.

    o GCC 4.4 build fixes.  Thanks for this go to Remi Collet.


3.0.8, 2008.11.27 (r2432) The "Thanksgiving" release

    o Fixed a VC++ build error introduced in 3.0.7 in the Sun CC fix.

    o Fixed the Makefile we generate from Makefile.simple for the
      devel RPM.  The recent Bakefile upgrade changed the output so
      our munger stopped munging.

    o Changed all instances of "CREDITS" in header comments to
      "CREDITS.txt".

    o Brought ebuild file up to date with what Gentoo has been
      using for 2.3.2.


3.0.7, 2008.11.21 (r2423)

    o Fixed bug where initting a Query with a query string and then
      appending more to it with operator <<() would start overwriting
      the beginning of the buffer.  Thanks for the fix go to Chris
      Frey.

    o Added String::empty(), to parallel std::string better.

    o Added SQLTypeAdapter ctor for Null<String>, to allow SSQLS with
      NULL BLOB columns.  Thanks for this patch go to Russell Robinson.

    o Passing on "throw exceptions" flag in Query::storein() to the
      temporary Row objects it creates.  (Should have done this
      all along.)

    o All MySQL++ classes with operator[]() and at() methods now
      throw the new BadIndex exception on out of range indices now,
      unconditionally.  Before, it was a mishmash of MySQL++-specific
      mechanisms, std::range_error, and unchecked access.

    o Fixed some bugs in load_jpeg and cgi_jpeg examples that prevented
      them from working correctly on Windows.

    o Squished some warnings and incompatibilities that caused
      difficulty with Solaris CC.

    o Several minor fixes to allow building on Cygwin again.

    o Dedicated VC++ 2008 support.  (Not just a clone of VC++ 2005
      project files in a different directory.)

    o Lots of documentation improvements.


3.0.6, 2008.08.16 (r2350)

    o Several fixes to allow thread-aware build on Solaris

    o More improvements to search for Fink version of C API library.

    o Various improvements to Windows installer (install.hta)


3.0.5, 2008.08.06 (r2332)

    o Replaced install.bat with new install.hta, which has a GUI and a
      lot of embeded logic for doing The Right Thing, which we couldn't
      do in a dumb batch file.

    o Several fixes to allow it to build on Solaris 10.

    o Fixed a bug in comparison of Null<T> to T: wouldn't always give
      the right result for one particular combination of argument
      values and order of parameters to operator <().  It wouldn't
      fail all the time, either; it depended on the way the system's
      memory allocator dealt with newly allocated RAM.  The bug was
      discovered during the Solaris 10 porting effort, but it is not
      a Solaris-specific bug.

    o Split Linux-specific material out of README-Unix.txt into
      README-Linux.txt, and created README-Solaris.txt.

    o Shipping a vc2008 directory.  Populated by bootstrap script with
      copies of vc2005 files when those are newer, with the idea being
      to update them by hand by running them through VC++2008 before
      release.

    o Several fixes to VS-only examples. They hadn't been updated to
      track several of the changes in MySQL++ v3, so they wouldn't
      build OOTB at all, crashed when you did get them building, and
      emitted a lot of warnings during the build.  Cleaned it all up.

    o Autoconf now explicitly checks whether we need to link to zlib
      to link to MySQL C API library.  It used to be required, but
      lately, MySQL has been shipping the library with zlib stuff
      embedded, causing multiply defined symbol errors on some systems.

    o configure script now looks in more locations for the MySQL C API
      library, adding default locations for Fink and Solaris.


3.0.4, 2008.07.02 (r2303)

    o Fixed a few bugs in SslOption that prevented it from actually
      working.  If you've been having SSL problems since upgrading
      to MySQL++ v3, this is why!  Thanks for these patches go to
      Petteri Kiiskinen.

    o Changed type of String's internal "size" typedefs so it'll
      build without errors on 64-bit systems where these ints are
      different sizes.

    o Many user manual improvements.


3.0.3, 2008.05.11 (r2284)

    o Fixed query well-formedness handling in Query::store() and use().
      It was quietly eating these errors, confusing them with the
      no-results case.

    o Fixed examples/cpool.cpp to build without thread support.

    o No longer hiding all stdint.h typedefs inside namespace mysqlpp.

    o Fixed mysqlpp::String comparisons of empty strings against
      nonempty strings; if the empty string was on the left hand side,
      it would succeed because it was only comparing against characters
      in the empty side, which matches everything.  (Fixes bug 11588.)


3.0.2, 2008.04.13 (r2275)

    o Increased float to string conversion precision from 7 to 9 and
      double from 16 to 17 digits.  Previous values weren't enough
      near the maximum values that each can hold.

    o Replaced Query's safe bool mechanism with an override of
      basic_ios::operator void*() to avoid a conflict between the
      two mechanisms.  As the base class version isn't virtual,
      this is arguably evil, but it should be harmless in typical use.
      Besides, testing Query in bool context usually isn't the right
      thing anyway: test the result set instead.

    o Made ConnectionPool::grab() virtual.

    o Overriding ConnectionPool::grab() and release() in
      examples/cpool.cpp to show how to do connection-in-use count
      limiting.  Also, added a few more output indicator states to
      allow one to better understand program flow.


3.0.1, 2008.03.23 (r2263)

    o String objects can now be compared to mysqlpp::null directly.

    o Added a template operator== and operator!= to String, syntactic
      sugar for the existing String::compare() methods.

    o String::compare() now returns 0 ("equal") when one of the
      strings is an uninitialized String() (no refcounted buffer)
      and the other is empty.  It used to consider any initialized
      string greater than an uninitted one.  An uninitialized String
      appears empty, though, so this was incorrect.

    o Made Connection::thread_aware(), thread_start() and thread_end()
      static methods, so they can be called before you create your
      first connection.  Ditto for DBDriver versions of these methods.

    o Calling Connection::thread_start() and thread_end() in
      examples/cpool.cpp, as appropriate.  Above changes were necessary
      to make this work sensibly.

    o Made ConnectionPool::release() virtual, so your pool subclass can
      override it.

    o Added ConnectionPool::size(), so a subclass can know the current
      number of extant connections.

    o No longer single-quoting NOW() call generated for default
      init of DateTime type when building queries from SSQLS objects
      in Query::insert(), replace() and update().  The template query
      and stream interfaces of Query treated NOW() correctly already.

    o Fixed a bug that left SSQLS::table_override_ uninitted if
      you used certain of the generated ctors or set() member
      functions instead of others used by the examples.  This could
      cause a crash any time you caused SSQLS.table() to be called,
      such as when passing the SSQLS to Query::insert().

    o Minor memset bug fixed in test/uds.cpp.  Patch by Dave Jones.


3.0.0, 2008.02.29 (r2236) The "Giant Leap Forward" release

    THIS IS NOT A DROP-IN REPLACEMENT FOR MySQL++ v2.x!

    You will have to recompile your program against this version
    of the library, and you will almost certainly have to make code
    changes as well.  Please see these sections in the user manual
    for information on migrating your code to this new version:

    http://tangentsoft.net/mysql++/doc/html/userman/breakages.html#api-3.0.0
    http://tangentsoft.net/mysql++/doc/html/userman/breakages.html#abi-3.0.0

    o Added ConnectionPool class, primarily to let multithreaded
      programs share a set of Connection objects safely in situations
      where it isn't acceptable to have a Connection per thread.

    o Created examples/cpool.cpp to demonstrate this new class.

    o Added RefCountedPointer template, which provides automatic
      memory management and data sharing.  It's not intended
      for use outside of MySQL++ itself, but it's the mechanism
      behind everything below where reference counting is mentioned.
      I created the initial version of it, but Jonathan Wakely almost
      completely rebuilt it, and Joseph Artsimovich provided helpful
      commentary and advice as well.

    o Many improvements to Specialized SQL Structures (SSQLS):

      - Renamed custom* to ssqls*.  There's still a custom.h which
        #includes ssqls.h for you, but it's only intended to ease
        the transition to the new name.  It will go away in a future
        release, probably as soon as v3.1.

      - SSQLSes are finally compatible with Null<>-wrapped types.  This
        feature is based loosely on the "Waba" patch posted to the
        mailing list back in the v2.0 days, but extended to allow
        Null<T> types for key fields.  (The Waba patch only allowed
        these types in non-key fields.)

      - It's no longer necessary to define a different SSQLS for each
        different field set you use in queries.  That is to say,
        you can define an SSQLS for an entire table and store just a
        subset of the table in it now, with the other fields keeping
        default values.  Removed examples/custom6.cpp, as custom1.cpp
        can now demonstrate the same thing, implicitly.

      - An SSQLS's field order no longer has to match the order of
        fields in the result set it is populated from.

      - As a result of previous, removed sql_create_c_order_* macros;
        they have no purpose now.

      - Removed order parameters from sql_create_complete_*, which now
        gives it the same functionality as sql_create_c_names_* so
        removed the latter, too.

      - Removed "basic" variants of SSQLS creation macros.  They've
        been unofficially deprecated by dint of being all but
        undocumented and unexemplified for a very long time now.

      - It's now possible to use mysqlpp::String, Date, DateTime, and
        Time types in the key field positions in an SSQLS as they
        now support the necessary comparison interfaces.

      - If you use a floating-point data type in one of the key field
        positions, it no longer uses exact comparison logic.  Instead,
        it now does [in]equality comparisons by testing whether the
        difference between two floating-point values is less than a
        configurable threshold defaulting to 0.00001.
    
      - You can now use 'bool' type in an SSQLS.

      - Renamed _table static member variable in each SSQLS to table_
        and made it private.  There are now public setter and getter
        methods, table().

      - Added per-instance table name overriding via instance_table()
        setter.  table() getter returns static version if this is not
        set, so it's still a global setting by default.

    o You can now use mysqlpp::null as a template query parameter to
      get a SQL null.

    o Replaced template ColData_Tmpl<T>:

      - Used to have typedef ColData_Tmpl<std::string> MutableColData.
        It was used only once within MySQL++ itself, and was never
        documented as a class for end users.  This one use within
        the library was a crock, so we just replaced this use with
        std::string and removed the typedef.

      - This left just one use of ColData_Tmpl<T>, instantiating it
        with the MySQL++ utility class const_string, basically a
        clone of std::string with all the mutating features removed.
        Folded the functionality of const_string into the template,
        renamed the result to String, and deleted the const_string
        class.  It'd be a complete std::string replacement -- with
        SQL-related enhancements -- if it were modifiable, but MySQL++
        doesn't need it to be modifiable.  Yet, it's still the closest
        thing MySQL++ has to its own string type; thus the name.

      - Replaced its internal buffer management with a much more
        clever reference counted scheme.  This shows its greatest
        advantage in the return from Row::operator[](), which for
        technical reasons must return by value, not by reference
        as is more common.  This lets you pass around Strings by
        value while having the efficiency of reference semantics.
        This can be important with large return values, like BLOBs.

      - Converting String to numeric types (ints, floats...) uses a
        new, cleaner system by Jonathan Wakely.  Unless you were
        abusing weaknesses in the old system, you won't see a
        difference.  It's just more robust and flexible.

    o Redesigned SQLString:

      - It used to derive from std::string, and while MySQL++'s
        internals did use it in place of std::string, these places
        didn't take advantage of the additional features offered
        by SQLString.  So, replaced all those uses with std::string.

      - All the remaining uses are MySQL++ public interfaces that
        need to be able to accept any of many different data types,
        and we want that data to be automatically converted to a
        SQL-compatible string form.  Because it no longer has the
        parentage to be a general-purpose string type and MySQL++ has
        a new contender for that role (String), renamed SQLString to
        SQLTypeAdapter to reflect its new, limited purpose.  ("STA"
        for short.)

      - Since we don't have the std::string base class to manage the
        string buffer any more, using the same reference counted
        buffer mechanism as String.  In addition to saving code by
        not creating yet another buffer management mechanism, it means
        objects of the two classes can share a buffer when you assign
        one to the other or pass one to the other's copy ctor.

      - Added many more conversion ctors.

      - STA interfaces using the 'char' data type now treat them as
        single-character strings instead of one-byte integers, as
        does the Standard C++ Library.

      - Added mysqlpp::tiny_int interfaces to STA to replace the
        former char interfaces for those needing one-byte integers.

    o As a result of the ColData -> String redesign, removed
      Row::raw_*().  Before String copies were efficient, this
      was helpful in accessing BLOB data efficiently.  It was also
      required back when ColData didn't deal correctly with embedded
      null characters, but that reason is gone now, too.

    o Row::operator[](const char*) no longer unconditionally throws the
      BadFieldName exception when you ask for a field that doesn't
      exist.  It will still throw it if exceptions are enabled, but if
      not, it'll just return an empty String.  This was necessary to
      make the SSQLS subset and field order independence features work.

    o Similarly, Result::field_num() returns -1 when exceptions are
      disabled and you ask for a field that doesn't exist.

    o You can now use the OptionalExceptions mechanism to disable
      exceptions on const MySQL++ objects.

    o Redesigned query result classes:

      - Instead of Result deriving from ResUse, the two derive from
        a common base class -- ResultBase -- containing the bits that
        are truly the same between them.  Before, Result inherited
        several methods that didn't really make sense for "store"
        query result sets.

      - Renamed Result to StoreQueryResult and ResUse to UseQueryResult
        so it's clearer what each is for.

      - Renamed ResNSel to SimpleResult.

      - Made all SimpleResult data members private and hid them behind
        const accessor functions of the same name.

      - The result set classes all used to be friends of Connection
        for various lame reasons.  Since they are created by Query,
        and Query has a good reason for a strong relationship with
        Connection, moved Connection access out of each result set
        class into the code in Query that creates that type of result
        set object.

      - StoreQueryResult now derives from vector<Row> in addition to
        ResultBase; it used to merely emulate a vector of Rows, poorly.
        It can now dispose of the MYSQL_RESULT at the end of object
        construction, because it creates all the Row objects up front
        instead of on the fly.  And as a result of *that*, operator[]
        returns by reference instead of by value, operator -> works
        correctly on iterators, all STL algorithms work, etc., etc.

      - IMPORTANT COMPATIBILITY BREAK: because we used fetch_row()
        stuff in Result previously, it was okay to index past the
        end of the result set: you'd just get a falsy Row when you
        did this, just as happens when doing the same thing in a
        "use" query.  The simple1 and simple2 examples did this,
        so it's likely that code exists that takes advantage of this
        misfeature.  New versions of these examples show how to index
        through a StoreQueryResult without running past its end.

      - ResUse used to delay creation of its FieldNames and FieldTypes
        objects until the point of need.  This had several implications
        for thread and exception safety that we fix by just creating
        them in the ctor.  If your code is multi-threaded and was
        avoiding certain usage patterns due to crashes, it's worth
        trying your preferred way again.

      - Result sets create a few data structures to hold information
        common to all rows in that set.  The row objects need access
        to these shared data structures, so on creation each gets
        a pointer back to the result set object that creates it.
        This was efficient, but required that a result set object
        outlive any row objects it creates.  Now these shared data
        structures are reference-counted, decoupling the lifetime of
        the child row objects from their result set parent.

      - Copy operations for result sets used to actually be "moves"
        before, for efficiency.  (MySQL++ itelf only copied result
        sets in returning them by value from the query execution
        methods of Query, so this was acceptable if you didn't do
        anything uncommon with these objects.)  Reference counted
        data structures allow us to have copy semantics now without
        sacrificing efficiency.

      - You can now use Query::storein() with an STL container of Row
        objects now, instead of having to use SSQLSes.  The lifetime
        issue guaranteed a crash if you tried this before.

      - Removed a bunch of unnecessary alias methods:

        - columns() -> num_fields()
        - names()   -> field_names()
        - rows()    -> num_rows()
        - types()   -> field_types()

      - Renamed several methods for grammar reasons:

        - fields(unsigned int)      -> field(unsigned int)
        - names(const std::string&) -> field_num(const std::string&)
        - names(int)                -> field_name(int)
        - types(int)                -> field_type(int)

      - Removed several "smelly" methods:

        - purge()
        - raw_result()
        - reset_names()
        - reset_field_names()
        - reset_types()
        - reset_field_types()

    o Field class used to just be a typedef for the corresponding C
      API class.  Now it's a real C++ class providing a more MySQL++
      sort of interface, plus good OO things like information hiding
      and implementation detail abstraction.  This changes several
      things about the interface.

    o Fields class was basically a specialized std::vector work-alike
      for dealing with the C API to get access to MYSQL_FIELD objects
      and present them as contained Field objects.  New Field type
      let us replace it with "typedef std::vector<Field> Fields"

    o Major improvements to the quoting and escaping mechanisms:

      - Replaced almost all of the type-specific interfaces in manip.h
        with a single version taking STA.  The compiler can convert
        almost anything to STA without losing any information we need
        for correct quoting and escaping.  This has the side benefit
        that we can now do correct quoting and escaping for more data
        types now, including plain C and C++ string types.

      - Fixed a bug in quote_double_only manipulator for String: was
        using single quotes by mistake.

      - Escaping and quoting only works in instances where MySQL++
        can tell you're building a SQL query and are using a data type
        that requires it.  This affects many things, but the one most
        likely to cause trouble is that inserting MySQL++'s quoting
        and escaping manipulators in non-Query ostreams is now a no-op.

      - Added escape_string() member functions to Query and
        SQLQueryParms::escape_string(), and removed the global function
        of the same name.  Because these are tied indirectly to a
        Connection object, this also has the effect that escaping is
        now aware of the current default character set used by the
        database server.  There's only one case where this isn't done
        now, and that's when we're disconnected from the server.

      - Previous two items form a trade-off: if your code was depending
        on MySQL++ to get SQL escaping and it no longer happens for
        what we consider a good reason, you can build a replacement
        mechanism using these new functions.  Quoting needs no special
        support in MySQL++.

      - Removed 'r' and 'R' template query parameter modifiers,
        which meant "always quote" and "always quote and escape"
        regardless of the data type of the parameter.  There are no
        corresponding manipulators (for good reason), so the removal
        restores symmetry.

    o Created DBDriver class from code previously in Connection and
      Query to almost completely wrap the low-level MySQL C API:

      - Connection creates a DBDriver object upon connection and
        passes a pointer to it down to Query objects it creates.
        In turn, they pass the pointer on to any of their children
        that need access to the C API.

      - Nothing outside DBDriver calls the C API directly now, though
        DBDriver leaks C API data structures quite a lot, so this
        feature doesn't constitute "database independence."  See the
        Wishlist for what must be done to get to that point.

    o Completely redesigned the connection option setting mechanism:

      - There's now just a single Connection::set_option() method that
        takes a pointer to the abstract Option base class, and there is
        an Option subclass for every connection option we understand.
        Thus, type errors are now caught at compile time instead of
        at run time.

      - Replaced Connection::enable_ssl() with SslOption class.

      - Enabling data compression and setting the connection timeout
        are no longer set via parameters to Connection interfaces.
        These are now set with CompressOption and ConnectTimeoutOption.

      - Similarly, removed client_flag parameters from Connection's
        ctor and connect() method and added corresponding Option
        subclasses.  There's about a dozen, so rather than list them
        here, look for similarly-named classes in lib/options.h.

    o Added Connection::count_rows() to execute "SELECT COUNT(*) FROM
      tablename" queries for you.

    o Moved Connection::affected_rows(), info() and insert_id() methods
      to class Query, as they relate to the most recently-executed
      query, not to the connection.

    o Several method name changes in Connection:

      - client_info()   -> client_version()
      - host_info()     -> ipc_info()
      - proto_info()    -> protocol_version()
      - server_info()   -> server_version()
      - stat()          -> status()

    o Removed Connection::api_version().  It does the same thing as
      client_version().

    o Lots of changes to Date, DateTime, and Time classes:

      - If you use the default constructor for DateTime and don't
        subsequently set its year, month, day, hour, minute or second
        data members to nonzero values, it becomes the SQL function
        "NOW()" in a query string.  You can also use DateTime::now()
        as syntactic sugar for this.

      - As a result of above, had to hide all of DateTime's data
        members behind accessor functions, to keep the state of the
        object consistent.  (If it's initialized as "now" and you
        give it an explicit year value, say, it is no longer "now",
        so the setter has to clear the now-flag.)  There are getters
        and setters for year, month, day, hour, minute and second,
        all named after the member.

      - Did the same for Date and Time for consistency, even though it
        isn't technically required.

      - The sql_timestamp typedef now aliases DateTime instead of Time.

      - Renamed template class DTbase<T> to Comparable<T>.  The fact
        that it's the common base class of all date and time classes
        is irrelevant; making subclasses comparable is what it does,
        so that's what it should be named after.

      - Added a DateTime ctor taking discrete year, month, day, hour,
        minute, and second values.

      - Implicit conversion from stringish types to the date and time
        types is no longer allowed.  This is part of the "Waba"
        Null<T> patch mentioned above; allowing implicit conversions
        would break this new feature.

      - Added operator std::string and str() methods to all of these
        classes.  Adding this to the existing operator << support, you
        now have several ways to convert these objects to string form.

      - Added time_t conversion to Date and Time classes.  DateTime
        already had it, since it's more legitimate to convert time_t
        to DateTime, but you could already "slice" it with something
        like Time(DateTime(time(0))) so there's no point pretending
        you can't get from time_t to Date or Time.  Might as well
        legitimize it.

    o Improved tiny_int class:
        
      - Turned it into a template parameterized on the value type so
        you can get both signed and unsigned TINYINTs

      - Changed the sql_tinyint and sql_tinyint_unsigned typedefs to
        use mysqlpp::tiny_int<VT> instead of raw chars

      - Added a bool conversion ctor and operator, and typedef'd it
        to sql_bool and sql_boolean to match MySQL server behavior

    o Added many more sql_* typedefs.  We now have a typedef for every
      type the MySQL server knows about, including those it supports
      just for compatibility with other database servers.

    o Changed the sql_*int* typedefs to use integer types of the same
      size as the MySQL server.  (Run test/inttypes.cpp to test it.)

    o Added copy ctor and assignment operator to Row.

    o Row::operator[]() takes int now instead of unsigned int.
      This finally (!) makes it possible to say row[0] without the
      compiler giving an ambiguous overload error.

    o Changed all uses of row.at(0) in the examples to row[0]

    o Added operator[] to all classes that only had at().

    o Query now automatically resets itself unless the query fails
      or you're using template queries.  In either case, the contents
      of the query's internal buffers are considered precious,
      either for debugging, or future queries.  Except when using
      template queries, this means you may be able to avoid calling
      Query::reset() entirely.  It's still safe to call reset()
      as before, just unnecessary most of the time.

    o Removed reset_query parameter from all Query methods.  It was
      almost completely broken before, and above change does what
      was really wanted to begin with.

    o Query::store_next() and Result::fetch_row() no longer throw
      the EndOfResults and EndOfResultSets exceptions; these are not
      exceptional conditions!  These methods simply return false now.

    o Removed examples/usequery.cpp: there's no essential difference
      between what it did and what examples/simple3.cpp does now as
      a result of the previous change.

    o Added Query::exec(void), paralleling Query::execute(void).

    o Removed Query::preview().  The most direct replacement is str(),
      which has always done the same thing.

    o You can now insert a Query object into an ostream to get a copy
      of the built query.  This means Query::str() is only necessary
      when using template queries.

    o Removed overloads of Query::execute(), store(), and use()
      that take const char*.  It was redundant because const char*
      converts implicitly to STA, for which overloads already exist.

    o Renamed Query::def to Query::template_defaults to make its
      purpose clearer.

    o Query::error() now returns const char*, not a std::string by
      value.  There's no point in making a copy of the error string.
      The method is now const as well, as it doesn't change the
      Query object.

    o Added Query::errnum(), which just wraps Connection::errnum().

    o Added error number parameters and accessor functions to BadQuery,
      ConnectionFailed and DBSelectionFailed exceptions, to preserve
      the state of Connection::errnum() at the point of the exception,
      so you don't have to rely on this value remaining unchanged
      during the exception throw process.  All places that use these
      exceptions now include this value where possible.  Thanks for the
      initial patch go to Jim Wallace.

    o Removed Lockable mechanism from Connection and Query; it was
      conceptually flawed.  See the new user manual chapter on
      threading for advice on using MySQL++ safely without locking.
      There is mutex locking now in ConnectionPool, but that's it.

    o Connection::query() now takes an optional query string, allowing
      the returned Query object to start off with a value.  Especially
      useful when the query string is static, either because it's
      a simple query or because it's a template.  You can now build
      chains like "if (conn.query("CREATE INDEX ...").exec()) { ..."

    o Added Connection::thread_aware(), thread_end(), thread_id()
      and thread_safe().  See user manual's threading chapter for
      explanations.

    o Renamed "success" data members in Connection, Query and
      SimpleResult (neé ResNSel) to "copacetic_", making them private
      if they weren't before.  This better reflects their actual
      use, which isn't to say that there has necessarily been actual
      success, but rather that everything's okay with the object.

    o Removed success() member functions from above classes.  All can
      be tested in bool context to get the same information.

    o Replaced all operator bool()s in MySQL++ classes with safer
      alternatives.  See http://www.artima.com/cppsource/safebool.html
      Thanks to Jonathan Wakely for much helpful commentary, advice,
      and code used in these mechanisms.

    o Decoupled Connection::copacetic_ from Connection::is_connected_.
      It is now possible for the object to be copacetic without being
      connected.  However, if it tries to connect and fails, then
      it is not copacetic.  If it is copacetic and not connected, it
      means we haven't even tried to connect yet, a useful distinction.

    o Collapsed Connection's host, port, and socket_name down into
      a new combined 'server' parameter which is parsed to determine
      what kind of connection you mean.  These interfaces are still
      compatible with v2.3 and earlier up through the port parameter.
      There are differences beyond this.

    o Added TCPConnection, UnixDomainSocketConnection and
      WindowsNamedPipeConnection subclasses for Connection giving
      simpler construction and connect() method interfaces for
      instances where you know what kind of connection you want at
      compile time.

    o Changed Connection::ping() return value from int to bool.

    o Renamed NullisNull to NullIsNull -- capital I -- and similar for
      NullisZero and NullisBlank.

    o It's now a compile-time error to try to convert a MySQL++
      representation of a SQL null to any other data type, rather
      than a run-time error as in previous versions.  Removed
      BadNullConversion exception as a result.

    o Way back in v1.7.x we used the BadQuery exception for all kinds
      of exceptional conditions, not just bad queries.  Replaced
      most of these in v2.0.0 with new dedicated exceptions, but a
      few remained:
      
      - Errors that occur during the processing of a "use" query after
        the query itself executes correctly now throw UseQueryError.
        It's not a "bad query", because the query executed
        successfully.  It just choked during subsequent processing,
        so it's a different exception.  Thanks for this patch go to
        Jim Wallace.

      - Replaced BadQuery exceptions thrown in Row constructor due
        to bad ctor parameters with new ObjectNotInitialized exception
        This is also Jim Wallace's work.

    o The examples now all use getopt() type command line options
      instead of positional options.  This makes it possible to
      pass options in any order, leave at their default options that
      used to be in the middle of the sequence, and offer different
      subsets of options for different programs.  Also allows for
      special internal-use options, like -D passed by dtest to let
      examples change their behavior when run under dtest to produce
      only predictable output.

    o Split old libutil functionality into two modules, one holding
      all the "print data" functions, and another holding all the
      command line parsing stuff.  This makes it easier for newbies
      to ignore the command line stuff, treating it like a black box.
      The wish to understand the "print data" routines is much more
      common, so the two needed to be disentangled.

    o Renamed examples' libutil to libexcommon.

    o Removed connect_to_db() libutil function.  It combined command
      line parsing, which users don't care about, with database
      connection establishment, which they do care about.  Now the
      examples just call out to libexcommon to parse the command
      line, and use the values they get back to explicitly make the
      connection, so it isn't hidden.

    o Removed cchar and uint typedefs.

    o Redesigned dbinfo example's output to be easier to read.

    o Fixed an output formatting bug created in 2.3.0 that caused the
      tabular output from examples to not line up.

    o Renamed examples/tquery.cpp to tquery1.cpp.  Created tquery2.cpp
      to demonstrate passing parameters via a SQLQueryParametrs object
      instead of discretely.  Created tquery3.cpp for testing unquoted
      template parameters, such as integers.

    o Renamed fieldinf1.cpp example to fieldinf.cpp, and simplified
      its output so it can be part of the dtest sequence.

    o Renamed examples/xaction.cpp to transaction.cpp.  It created too
      much cognotive dissonance whenever thinking about both it and
      lib/transaction.cpp.

    o Added examples/deadlock.cpp, to test handling of exceptions due
      to server-side transaction deadlock detection.  Also added
      code to resetdb to create a table needed to test this.
      Initial version created by Jim Wallace to test the value of
      all his BadQuery exception work, with reworking by me.

    o Greatly expanded dtest suite.  Primary change is that we now
      have a handful of unit tests, where in v2.3.2 we only tested
      a subset of the examples.  Still very low coverage ratio,
      but it's a big improvement.

    o Optimized #includes, especially in lib/*.h to reduce
      dependencies and thus compile time when one of these changes.

    o Fixed a typo in RPM filename generation that prevented -devel
      RPM from recognizing that the corresponding MySQL++ library
      RPM was installed.

    o RPM spec file improvements by Remi Collet.

    o Renamed NO_LONG_LONGS to MYSQLPP_NO_LONG_LONGS to avoid a risk
      of collision in the global macro namespace.
    
    o First cut at Xcode2 project support.  Testing needed!

    o Debug build of library on VC++ and Xcode have a _d suffix now
      so you can have both versions of the library installed without
      conflict.

    o Moved the VC++ 2003 project files into a new vs2003 subdirectory
      because there are so many of them.  Also created vs2005
      subdirectory for VC++ 2005 and 2008 compatible project files.
      2005 makes an even bigger mess of the directory containing
      the .sln file, so the incentive is bigger.  Plus, we have to
      disable several things to get VC++ 2003 to build MySQL++ now,
      so we need a special 2005+ version of the project files for a
      complete build, if the user has one of the newer compilers.

    o ...plus dozens of small bug fixes and internal enhancements,
      many documentation improvements, and expansion of support for
      newer operating systems and compilers.


2.3.2, 2007.07.11 (r1669)

    o Previous release's const_string change caused more problems
      than it fixed.  This release contains the real fix. :)

    o New Connection::set_option() handling deals with the multi
      statements option correctly again.  examples/multiquery now
      runs again as a result.

    o Added new unit testing script, called dtest.  See the
      HACKERS file for details.  (This tool caught the previous
      two problems!)

    o Squished a GCC pedantic warning.  Thanks for the patch go to
      Andrew Sayers.


2.3.1, 2007.07.10 (r1659) The "After the Fireworks" release

    o const_string objects now keep a copy of their data, not
      just a pointer to it.  This is less efficient, but necessary
      to allow SSQLS to work with BLOBs.  Without this, we were
      seeing segfaults due to accessing freed memory pointed to
      by the const_string, because the underlying object went
      out of scope.

    o Fixed many more potential embedded null handling problems
      in manip.h.

    o MySQL++ can now optionally reference MySQL C API headers as
      being in a mysql subdirectory, a common thing on *ix systems,
      by defining MYSQLPP_MYSQL_HEADERS_BURIED before #including
      mysql++.h.

    o Restored ColData_Tmpl<T>::get_string(), removed in v2.3.0,
      along with warnings in the docs saying why you don't want
      to use it, and what your alternatives are.

    o VC++ and MinGW builds now define the HAVE_MYSQL_SSL_SET
      macro, which lets you use the C API's SSL features.
      This assumes your C API library does actually have these
      features enabled, which is the case with the official binary
      releases on Windows.  (Builds on *ix systems continue to
      test for these features at configure time.)

    o Fixed simple examples-only Makefile generation, for RPMs.


2.3.0, 2007.07.02 (r1645)

    o Added Query::for_each() and Query::store_if() methods
      proposed by Joel Fielder, and added examples for each.

    o It's now possible to store BLOB data in an SSQLS.  It's not
      foolproof, so added a section to the user manual (5.9) to
      document the method.  Also, changed examples/cgi_jpeg to use
      this new mechanism, instead of the ugly "raw row data" method
      it used to use.

    o Revamped Connection::set_option() handling.  These options
      used to be queued up, and applied only just before actually
      establishing the connection.  This made error reporting less
      helpful because the diagnostic was separated from the cause.
      Plus, the error messages were misleading to begin with.  Now,
      set_option() takes effect immediately if the connection is not
      yet up (excepting one special option that can actually be set
      after the connection is up) and issues better diagnostics when
      it detects errors.

    o Connection::connect() used to set a few options in such a
      way that the user couldn't override them.  Now it's smart enough
      to set them with the desired default values only when we see
      that the user hasn't given them other values.

    o SQLString can now be initialized from a mysqlpp::null,
      giving a "NULL" string.  This is useful for template queries.
      Patch by Michael Hanselmann.

    o resetdb error message about mixing library and header version
      numbers is now more explicit.

    o Changed BadConversion exception's "what" message text to be
      more like the other exceptions.  The inconsistency lead one
      to incorrectly copy-paste code from another exception handler,
      expecting it to behave the same way.  Now it does.

    o Added Row::raw_size(), as a shortcut for Row::at().size().

    o ssqls-pretty now detects when it's being run from within
      the MySQL++ distribution tree and gives a different -I flag
      to the compiler, so that it picks up the distribution headers
      instead of those that may be on the system already.

    o The quote manipulator now works for char[] correctly.
      Thanks for this patch go to Andrew Sayers.  (It's always
      worked for char*, but C++ doesn't consider that to be the
      same type, so it used the generic quote handling path,
      which doesn't do anything for char[].)

    o Fixed a build bug on older Solaris versions where the
      test for the C API library was erroneously failing, stopping
      the configuration process.

    o Simplified mysql_shutdown() level argument detection.
      Already had to do a version number ifdef check for the
      Windows case, so there's really no point to doing it with
      autoconf on Unixy platforms.  Moved version number check
      into lib/connection.cpp, and nuked the separate autoconf and
      Windows tests.

    o Removed dependency of sql_types.h on myset.h and (indirectly)
      datetime.h.  Now we only define sql_* typedef aliases for those
      MySQL++ types if the headers are included before sql_types.h.

    o Fixed a typo in one of the storein_sequence() template
      overloads, which is apparently rarely (or never?) used, because
      no one reported the compiler error you'd get if you tried.

    o Fixed a few more embedded null handling problems.

    o ColData used to keep two copies of all data it held.
      Now it keeps just one.

    o Fixed install.bat script to track the unified Bakefile change
      and the lack of separate debug and release builds under MinGW.

    o Yet another STLport + Query memory leak fix.

    o Squished a warning in newer GCCs having to do with identifier
      shadowing.  Patch by Jonathan Wakely.

    o Fixed a null-termination bug in Query::parse().  If you
      somehow constructed a query string without a terminating null
      character, then tried to parse it as a template query, it could
      walk off the end of the string.  Patch by Worster Chen.

    o Removed MYSQLPP_EXPORT tag from FieldNames and FieldTypes
      class declarations, as this can cause problems in programs
      that use vector<string> in VC++.  It has to do with multiply
      defined templates, since these classes derive from that
      template, and VC++ can't resolve the conflict without help.
      Since these classes aren't actually used outside the library,
      this shouldn't cause a problem.  Patch by Nils Woetzel.

    o Partial fix to Doxygen PDF build on RHEL4 and 5.  Needs
      hand-coaxing to complete successfully on RHEL4, and doesn't
      yet work at all on RHEL5.

    o Shortened the "no*" options to the bootstrap script, so that
      the usage message fits on a single line.

    o Added "nodoc" bootstrap script option, for disabling the
      documentation build during the dist target build.  Allows for
      building binary RPMs on CentOS 5.0, where doc building is
      currently broken.

    o Removed the updel example program.  It was kind of silly,
      and if you were to rewrite it today, you'd use for_each() anyway.

    o Lots of documentation improvements.


2.2.3, 2007.04.17 (r1538) The "Tax Day" release

    o Previous version left examples/vstudio/* out of the tarball
      by accident.

    o Improved generation of RPM temporary build directory path
      name generation.  Was using a hacked variant of the Fedora
      Packaging Guidelines' second best choice.  Now we're using
      the choice they recommend most highly, without changes.

    o Removed unnecessary resources from vstudio/wforms example.

    o Minor URL fix in refman


2.2.2, 2007.04.13 (r1526) The "Nervousmaking Friday the 13th" release

    o More small fixes to embedded null handling in Query.

    o Fixed a bug in single-parameter template query handling.

    o Added tquery example, to demonstrate proper use of template
      queries.  Previously, resetdb was the only exemplar, and
      it wasn't really suited for that.  This example also tests
      the previous item.

    o Added examples/vstudio/mfc, allowing us to improve the way
      we demonstrate Unicode handling.  Old way wasn't realistic.
      On *ix, people will depend on the terminal code to handle
      UTF-8.  On Windows, users are almost certain to be writing
      a GUI program, which requires different Unicode handling
      than the old examples showed.

    o Removed explicit Unicode conversion stuff from command line
      examples, and reworked the Unicode chapter in the user
      manual.
    
    o Added examples/vstudio/wforms to show integration with
      C++/CLI and Windows Forms.  Documented this in README.vc.

    o Rewrote load_file and cgi_image examples to be more
      useful, renaming them to load_jpeg and cgi_jpeg along
      the way.  Also, resetdb now creates a second table in the
      sample database for these two examples' use.  Also, added
      examples/logo.jpg to the distribution as sample data for
      these examples.

    o Limited the ostream base class casting stuff in Query to
      VC++ 2003, which is the only platform that really needed it.
      VC++ 2005 emits a warning with that hack in place, and on
      other platforms it's just replicating work that the compiler
      does already.

    o Added library version information to main library target
      so that systems that version shared libraries work as
      expected.  Thanks for this patch go to Jack Eidsness.

    o Merged much of the diffs between Remi Collet's RPM spec file
      into the official one.

    o Reorganized the doc subdir a bit.  Generated HTML is now all
      under doc/html instead of scattered under other subdirs,
      and renamed doc/README.mysql++ to doc/README.manuals.

    o Improvements to top-level manual building make targets:
      manuals now only rebuild at need, it's easier to request
      a rebuild of all manuals, and we force a rebuild attempt
      before building the distribution tarball so we don't ship
      outdated manuals.

    o Added ability to run examples under gdb using exrun,
      using same mechanism as we currently have for valgrind.
      Thanks for this patch go to Michael Hanselmann.

    o Added "Important Underlying C API Limitations" chapter to the
      user manual, to cover problems we keep seeing on the
      mailing list that are the result of ignorance of the way
      libmysqlclient behaves, not bugs MySQL++ is really in a
      position to fix.


2.2.1, 2007.02.28 (r1433)

    o Fixed the new localtime() alternative selection code
      for VS2003 and various uses of STLport.

    o No longer inserting a null character into the query stream
      on calling one of the preview() functions.  This was harmless
      in v2.1, which used C strings more extensively, but began
      causing problems in v2.2 due to its wider use of C++ strings.

    o Fixed a bug in the Connection copy ctor where it didn't
      completely initialize the object.

    o Optimized Query::preview_char() a bit.  Patch by Jonathan
      Wakely.

    o Reordered directory list used by autconf when locating the
      MySQL C API library.  The list is now ordered with the
      most likely locations for the library first, so we're less
      distracted by incorrect libraries.  This fixes a specific
      build error under RHEL4 with recent versions of MySQL 5.0.


2.2.0, 2007.01.23 (r1417)

    o ColData, const_string, and SQLString can now be constructed
      with an explicit length parameter.  Furthermore, Query
      class's execute(), store() and use() call chains terminate
      in a version taking an explicit length parameter, instead
      of one taking a simple C string.  Together, this means
      that it's now easier to handle data from the SQL server
      containing nulls.  The library is almost certainly not yet
      capable of handling embedded nulls in all cases, but this
      is a big first step towards that.

    o Can now construct a DateTime object from a time_t, and
      convert a DateTime back to a time_t.  Patch by Korolyov Ilya.

    o Changed the way we're handling exported functions in the
      Windows DLL case so that it works more reliably under MinGW.

    o Added proper copy semantics to Connection, so that you get a
      new connection with the same parameters, not just a bitwise
      copy of the object.

    o Using an explicitly thread-safe variant of localtime() for
      time conversions where one is available.

    o Removed ListInsert template from myset.h.  This wasn't used
      within the library, and was never documented, so I'm betting
      that no one actually uses it.

    o Result::copy() was not copying the exception flag in
      all cases.  Fix by Steven Van Ingelgem.

    o Added exrun shell script and exrun.bat files to distribution,
      to avoid linkage errors when running the examples while
      you still have an older version of MySQL++ installed.

    o Renamed MYSQLPP_LIB_VERSION to MYSQLPP_HEADER_VERSION, as
      what it really encodes is the version number in the mysql++.h
      file you're using, not the actual library version number.

    o Added mysqlpp::get_library_version(), which returns the
      library version number at build time.  Between this and
      the header version constant, you can check that you're not
      mixing MySQL++ header and library versions.

    o resetdb example uses these new version number affordances to
      double-check that you're not mixing libraries and headers
      from different versions.  This happens easily unless you
      take care of it (such as by using exrun) when you have one
      version of MySQL++ installed and you're trying to build and
      test a new version without blowing away the old one first
      or overwriting it.

    o No longer using recursive Makefiles on Unixy platforms
      or split lib + examples project files on VC++.  Everything is
      handled by a single top-level Makefile or project file, which
      is simpler for the end user, and makes better dependency
      management possible.

    o When looking for the MySQL C library on systems using
      autoconf, looking in .../lib64 wherever we are also looking
      in .../lib.

    o RPM build process no longer depends on Bakefile.  It means
      you have to build the examples when building an RPM even
      though they're never used within the RPM, but it's a better
      tradeoff in my opinion.

    o Updated include and library paths on Windows to reflect
      changes in the most recent MySQL installers.

    o Merged lib/defs.h and lib/platform.h into new file,
      lib/common.h.  Just cleans up the library internals.

    o Fixed build errors on Windows due to recent changes in MySQL.

    o Fixed a few memory leaks and double-deletes in Query class.

    o Fixed compatibility with STLPort's string implementation.
      Patch by dengxy at cse.buaa.edu.cn.

    o Fixed a compatibility problem between Set<> template and
      SSQLS.  Patch by Korolyov Ilya.

    o Fixed build bug in SQLQueryParms due to a character
      signedness issue on PowerPC with GCC.  Patch by Michael
      Hanselmann.

    o ~Transaction() can no longer throw exceptions.  It'll just
      quietly eat them, to avoid program termination.  Fix
      suggested by Alex Burton.

    o Fixed thread safety testing in autoconf case, accidentally
      broken during v2.1.0 development cycle.

    o Using Doxygen 1.5.1 to generate documentation.


2.1.1, 2006.04.04 (r1289)

    o MinGW and Cygwin will now build and link to mysqlpp DLLs.

    o Fixed bug in Query, causing it to initialize the "throw
      exceptions" flag incorrectly.  Thanks for this patch go to
      Joel Fielder.

    o Added -v flag for custom.pl script, which turns off the
      multiply-defined static variable fix.  Needed for VS 2003,
      which doesn't support variadic macros.  Also, added
      a diagnostic to detect the need for the -v flag, and
      suppressed the test for this feature in examples/util.cpp.


2.1.0, 2006.03.24 (r1269)

    o Converted automake and makemake files to their equivalents in
      Bakefile format.

    o Added the Transaction class, which makes it easy to use
      transaction sets in MySQL++.

    o Added xaction example to test new Transaction class.

    o Resetdb example now creates its example table using the
      InnoDB storage engine, in order to test the new transaction
      support.  Resetdb also declares the table as using UTF-8
      text; this doesn't change anything, but it does correctly
      document what we're doing.

    o Added sql_types.h header, containing C++ typedefs
      corresponding to each MySQL column type.  Using those new
      types in the type_info module, and in the SSQLS examples.

    o Replaced the way we were handling the template query
      version of Query member functions, to allow an arbitrary
      number of template query parameters.  By default, we
      now support 25 parameters, up from the old limit of 12.
      It's now possible to change just one number, run a script,
      and have a new limit.

    o Connection class does a better job of returning error
      messages if you call certain member functions that depend
      on a connection to the server before the connection is
      established.

    o Updated libmysqlclient.def for newer versions of MySQL.  (Fixes
      build errors having to do with mysql_more_results() and
      mysql_next_result().

    o Replaced final use of strcpy() with strncpy().

    o custom.pl now runs without complaint in strict mode, with
      warnings turned on.  Thanks for this patch go to "Waba".

    o Fixed a bug in custom.pl where incorrect code would be
      generated for some SSQLS set() methods.  Thanks for this
      patch go to "Waba".

    o SSQLS structures now support long and unsigned long fields.
      Thanks for this patch go to "Waba".

    o It's now possible to put SSQLS definitions in a header
      file used by multiple modules in a program without
      getting multiple static member definition errors.  See the
      documentation for details.  Thanks for this patch go to
      Viktor Stark.

    o Moved the definition of the 'stock' SSQLS out of the
      custom*.cpp example files and into a new stock.h file.
      Also, #including that file in the util module to test out
      the new SSQLS multiple static definition fix.

    o Using all of the digits of precision guaranteed by the
      IEEE 754 spec when stringizing floating point numbers
      to build queries.  Previously, we would use the platform
      default, which can be as few as 6 digits.

    o Removed lib/compare.h.  Not used within the library, never
      documented, and nobody seems to want to defend it.


2.0.7, 2005.11.23 (r1147)

    o Added explicit mysqlpp namespace qualifiers to generated code in
      custom*.h so you can use SSQLS in places where it doesn't make
      sense to say "using namespace mysqlpp" before the declaration.
      Also updated some of the examples to not have this "using"
      declaration to make it clear to users that it isn't needed, if you
      want to use explicit namespace qualifiers as well.  Thanks for
      this patch to Chris Frey.

    o Removed an apparently useless unlock() call from ResUse; there is
      no nearby lock() call, so if this unlock() is in fact necessary,
      it shouldn't be here anyway, because the two calls should be
      nearby each other.  Thanks for this patch to Chris Frey.

    o Fixed Query ostream initialization bug affecting SunPro CC (at
      least).  While this bug violates the Standard, it doesn't affect
      many real compilers because they don't enforce this rule.  Fixed
      by Chris Frey.

    o Previously, we only used the C99 style "long long" support when
      building under GNU CC.  This is now the default.  This should
      allow the code to work under SunPro CC.

    o Added another dynamic cast needed for proper Query ostream
      subclass overloading under VC++.  (7.1 at least...)

    o Detecting whether MySQL is built with SSL support on platforms
      using autotools.  Needed on some old Sun systems, for instance.
      Thanks for this patch to Ovidiu Bivolaru.

    o Fixed a potential memory bug in ColData's conversion to SQL null.

    o Many minor packaging tweaks.  (README clarifications, file
      permission fixes, better adherence to GNU packaging standards,
      etc.)

    
2.0.6, 2005.09.28 (r1123)

    o Fixed makemake.bat so it works on cmd.exe, not just 4NT.

    o Documentation fixes.


2.0.5, 2005.09.13 (r1114)

    o Visual C++ build now requires GNU make.  It is tested to work
      with either the Cygwin or the MinGW versions.  The previous
      version of MySQL++ used nmake.  This change enabled the
      following features:

        o Debug and Release versions are both built into
          separate subdirectories.

        o Dependency tracking for release version works
          correctly now.  (Previously dependencies worked
          only for debug version.)

        o 'make clean' removes release version binaries
          in addition to debug versions.

    o MinGW makemake support updated to support new release/debug
      subdirectory system.  This is probationary support, since
      this code currently can't be built as a DLL.  As a result,
      it is no more useful than the Cygwin version, for licensing
      reasons.

    o Several fixes to allow building on Solaris 8.  These fixes may
      also help on other SVR4-derived systems.

    o Removed Borland C++ makemake support, because this version
      of the library does not work completely, and there seems
      to be almost no user interest in fixing it.
      
    o Clarified "Handling SQL Nulls" section of user manual's
      Tutorial chapter.


2.0.4, 2005.08.29 (r1076)

    o Made mysql_shutdown() second parameter autoconf check less
      sensitive to compiler pedantry.

    o VC++ library Makefile is now smart enough to re-create the
      import library, if it is deleted while leaving the DLL alone.

    o Added libmysqlclient.def to tarball.

    o Reworked most of the top-level README* files.

    o Renamed LGPL file to LICENSE.


2.0.3, 2005.08.25 (r1060)

    o Visual C++ makemake system updated to build both debug and
      release versions of library DLL.

    o Fixed bug in simple1 example that caused crashes on Windows.

    o Doing UTF-8 to ANSI text translation in simple examples now.

    o Previous two releases built libmysqlpp with wrong soname on
      autotools-based systems.  Fixed.


2.0.2, 2005.08.18 (r1050)

    o Fixes to makemake system for cmd.exe.

    o Fixed the case where the system's C++ library includes an slist
      implementation in namespace std.


2.0.1, 2005.08.17 (r1046)

    o Added new simple1 example, showing how to retrieve just one
      column from a table.  Old simple1 is now called simple2, and
      simple2 is likewise shifted to simple3.

    o Added custom6 example, showing how to do the same thing with
      SSQLS.

    o Updated user manual to cover new examples.

    o Was accidentally shipping Subversion crap with tarball.  Fixed.


2.0.0, 2005.08.16 (r1031) The "Excess Hair Removal" release

    THIS IS NOT A DROP-IN REPLACEMENT FOR MySQL++ v1.7!

    At minimum, you will have to recompile your program against
    this library.  You may also have to make code changes.
    Please see the "Incompatible Library Changes" chapter of
    the user manual for a guide to migrating your code to this
    new version:

        http://tangentsoft.net/mysql++/doc/html/userman/breakages.html

    o The library's shared object file name (soname) scheme has
      changed.  (This mainly affects POSIX systems.)
      
      The soname for the last 1.7.x releases of MySQL++ was
      libmysqlpp.so.4, meaning the fourth version of the library's
      application binary interface (ABI).  (The first ABI version
      in this scheme was that provided by 1.7.9.)  MySQL++
      2.0.0's soname is libmysqlpp.so.2.0.0.  Since the dynamic
      linker setup on some systems will create a symlink to
      that file called libmysqlpp.so.2, it's possible that this
      library could be confused with that for MySQL++ 1.7.19
      through .21, which also used this number.  Do not install
      this library on a system which still has binaries linked
      against that version of the library!

      The new scheme is {ABI}.{feature}.{bug fix}.  That is,
      the first number changes whenever we break the library's
      binary interface; the second changes when adding features
      that do not break the ABI; and the last changes when the
      release contains only internal bug fixes.  This means
      that we will probably end up with MySQL++ 3.0 and 4.0 at
      some point, so there will be further soname conflicts.
      Hopefully we can put these ABI changes off long enough
      to avoid any real problems.

    o autoconf now installs headers into $prefix/include/mysql++,
      instead of $prefix/include.  If you were using the
      --includedir configure script option to get this behavior
      before, you no longer need it.

    o Linux binary RPMs will henceforth include only the
      libmysqlpp.so.X.Y.Z file, and create any short names
      required, to allow multiple versions to be installed at
      once.  Currently, you cannot install two MySQL++ library
      RPMs at once, because they both have /usr/lib/libmysqlpp.so.X,
      for instance.

    o Replaced the Visual C++ and Borland C++ project files with
      a new "makemake" system, which creates Makefiles specific
      to a particular toolchain.  This new mechanism also supports
      MinGW and generic GCC-on-*ix.  This was done partly to reduce
      the number of places we have to change when changing the
      file names in MySQL++ or adding new ones, and partly so we're
      not tied to one particular version of each of these tools.

    o VC++ Makefiles create a DLL version of the library only
      now, so there's no excuse for LGPL violations now.
      This same mechanism should make DLL builds under other
      Windows compilers easy.

    o Added Connection::enable_ssl(), which enables encrypted
      connections to the database server using SSL.

    o Connection::create_db() and drop_db() now return true on
      success, not false.

    o Connection::create_db() and drop_db() use Query::exec()
      now, for efficiency, rather than Query::execute().

    o Removed Connection::infoo().  Apparently just there to
      save you from a typo when calling the info() method, since
      it was a mere alias.

    o Renamed Connection::real_connect() to connect(), gave
      several more of its parameters defaults, and removed old
      connect() function.  Then changed user manual and examples
      to use new APIs.

    o Replaced Connection::read_option() with new set_option()
      mechanism.  The name change matches the method's purpose
      better.  Functional changes are that it returns true on
      success instead of 0, it supports a broader set of options
      than read_option() did, and it enforces the correct option
      argument type.

    o You can now call Connection::set_option() before the
      connection is established, which will simply queue the option
      request up until the connection comes up.  If you use this
      feature, you should use exceptions, because that's the only
      way an option setting failure can be signalled in this case.

    o Removed query-building functions (exec*(), store*(),
      use()) from class Connection, and moved all the implementation
      code to class Query.  Query no longer delegates the final
      step of sending the query to the database server to
      Connection().

    o Added Connection::enable_ssl(), for turning on SSL support on
      a connection.

    o Extracted exception disabling mechanism out of the many
      classes that had the feature into a new OptionalExceptions
      base class, which all classes having this feature now
      derive from.  Also, removed all per-method exception
      handling flags.  Finally, added NoExceptions class.  With
      all of these changes, there is now a common way to disable
      exceptions with fine granularity on all objects that
      support the feature.

    o All custom MySQL++ exceptions now derive from the new
      Exceptions class.  This regularizes the exception interface
      and allows you to use a single catch() block if you want.

    o The "throw exceptions" flag is passed from parent to child
      in all situations now.  (Or if not, please report it as
      a bug.) This fulfills a promise made in the v1.7.9 user
      manual, with the cost being that some programs will see
      new exceptions thrown that they're not expecting.

    o Added a bunch of new exception types: BadOption,
      ConnectionFailed, DBSelectionFailed, EndOfResults,
      EndOfResultSets, LockFailed, and ObjectNotInitialized.
      Some of these replace the use of BadQuery, which in v1.7.x
      was a kind of generic exception, thrown when something more
      specific wasn't available.  Beware, this means that programs
      may start crashing after recompiling them under v2.0 due to
      uncaught exceptions, if they were only trying to catch BadQuery.

      There are additional instances where the library will
      throw new exceptions.  One is when calling a method that
      forces the internals to use an out-of-bounds index on a
      vector; previously, this would just make the program
      likely to crash.  Another is that the library uses the
      BadFieldName exception -- created in v1.7.30 -- in more
      apropos situations.

    o Renamed SQLQueryNEParms to BadParamCount, to match naming
      style of other concrete exception types.

    o Extracted lock()/unlock() functions from Connection and
      Query classes into a new Lockable interface class.  Locking
      is implemented in terms of a different class hierarchy, Lock,
      which allows multiple locking strategies with a single ABI.

    o Removed ResUse::eof().  It's based on a deprecated MySQL
      C API feature, and it isn't needed anyway.

    o Removed arrow operator (->) for iterator returned by Fields,
      Result and Row containers.  It was inherently buggy, because
      a correct arrow operator must return the address of an
      object, but the underlying element access functions in these
      classes (e.g. at()) return objects by value, of necessity.
      Therefore, this operator could only return the address of
      a temporary, which cannot be safely dereferenced.

    o Returned Row subscripting to something more like the
      v1.7.9 scheme: there are two operator[] overloads, one for an
      integer (field by index) and another for const char* (field
      by name).  lookup_by_name() has been removed.  Because row[0]
      is ambiguous again, added Row::at() (by analogy with STL
      sequence containers), which always works.

    o Collapsed two of the Row::value_list*() overloads into
      two other similar functions using default parameters.
      This changes the API, but the removed functions aren't
      used within the library, and I doubt they are used outside,
      either.

    o Merged RowTemplate into Row.

    o Merged SQLQuery class into Query class.

    o Query is now derived from std::ostream instead of
      std::stringstream, and we manage our own internal string
      buffer.

    o Moved SQLParseElement and SQLQueryParms into their own
      module, qparms.

    o Added multiple result set handling to Query.  MySQL 4.1
      and higher allow you to give multiple SQL statements in a
      single "store" call, which requires extensions to MySQL++
      so you can iterate through the multiple result sets.  Also,
      stored procedures in MySQL 5.0 reportedly return multiple
      result sets.  Thanks for the initial patch go to Arnon Jalon;
      I reworked it quite a bit.

    o Query::storein*() now supports more varieties of the
      nonstandard slist comtainer.  (Singly-linked version of
      STL std::list.)

    o Template query mechanism and user manual had several
      mismatches.  Made manual match actual behavior, or
      made library match documented behavior, as apropriate.
      Initial patch by Jürgen MF Gleiss, with corrections and
      enhancements by Warren Young.

    o Collapsed mysql_* date and time base classes' methods and
      data into the subclasses.  Also, DateTime no longer derives
      from Date and Time; you could get away with that in the
      old hierarchy, but now it creates an inheritance diamond,
      and allows unsupported concepts like comparing a Time to
      a DateTime.

    o Removed "field name" form of Row::field_list().  It was
      pretty much redundant -- if you have the field names, why
      do you need a list of field names?

    o ColData can convert itself to bool now.  Thanks for this
      patch go to Byrial Jensen.

    o Removed simp_list_b type; wasn't being used, and doesn't
      look to be useful for end-user code.

    o Several methods that used to take objects by value now
      do so by const reference, for efficiency.

    o Several variable and function renamings so that MySQL++
      isn't needlessly tied to MySQL.  Even if we never make
      the library work with other database servers, there's
      little point in tying this library to MySQL blindly.

    o Renamed all private data members of MySQL++ classes to
      have trailing underscores.

    o 'private' section follows 'public' section in all classes
      now.

    o Removed mysql++.hh and sqlplus.hh backwards-compatibility
      headers.

    o Added copy ctors to Date/Time classes so that they will
      work in SSQLS under GCC 4.0.0.  Without these, the compiler
      couldn't make the conversion from raw MySQL row data.

    o Fixed a bunch of GCC 4.0 pedantic warnings: added virtual
      dtors to all base classes, calling base class ctors from leaf
      classes, etc.

    o All warnings fixed under VC++ at warning level 3.  (Mostly
      harmless signedness and integer conversion stuff.)

    o Updated LGPL license/copyright comments at the top of
      several files to use FSF's new physical address.

    o Relicensed user manual under a close variant of the Linux
      Documentation Project License, as it's designed for
      documentation, which the LGPL is not.  Permission for this
      received from Kevin Atkinson and MySQL AB.

    o Added ABI and API breakages chapter to user manual.  It
      is basically a subset of this ChangeLog, with only the
      information an end-user must know when migrating between
      versions.

    o Reworked user manual's DocBook code quite a bit after
      reading Bob Stayton's book "DocBook XSL" 3/e.  Better handling
      of stylesheets, taking advantage of some superior DocBook
      features, prettier output (especially the HTML version), etc.

    o Rewrote doc/userman/README to make it clearer how to get
      started contributing to the user manual.  It's essentially a
      "getting started with DocBook" guide now!

    o Lots of small text improvements to user and reference
      manuals.  Aside from the obvious tracking of library changes,
      made a bunch of minor style and clarity improvements.

    o Added CSS stylesheets for userman and refman to
      make the HTML versions of each a) not ugly; and b) match
      tangentsoft.net.  (Yes, some may say that these are incompatible
      goals....)

    o Standardized exception handling code in the examples that
      use it.

    o Fixed a potential memory leak due to exceptions thrown from
      ResUse.  Thanks for this patch go to Chris Frey.

    o Using new "no exceptions" feature of library in simple1
      example, so it is now truly simple.

    o simple1 example no longer depends as much on util module, so
      that all of the important code is in one place.  Makes
      learning MySQL++ a little less intimidating.

    o Added new simple2 and usequery examples, to demonstrate
      the proper way to handle a "use" query, with exceptions
      disabled, and not, respectively.  Added them to the user
      manual, in the appropriate place.

    o Refactored the "print stock table" example functions
      again, to make code using them clearer.

    o UTF-8 to UCS-2 handling in examples is now automatic on
      Windows.

    o Removed debug code from Windows Unicode output examples
      that slipped into previous release.

    o resetdb example is now clearer, and more robust in the
      face of database errors.

    o Simplified connect_to_db() in examples' util module.

    o Added sample autoconf macro for finding MySQL++ libraries, for
      people to use in their own autotools-based projects.

    o Lots and lots of minor cleanups not worth mentioning
      individually...


1.7.40, 2005.05.26 (r719)

    o Multiple item form of insert() now works if you're using the
      SQLQuery class, or its derivative, Query.  Thanks to Mark
      Meredino for this patch.

    o Fixed a bug in const_string::compare(), in which MySQL++
      would walk off the end of the shorter of the two strings.
      All was well if the two were the same length.

    o ResUse::operator=() now fully updates the object, so it's more
      like the behavior of the full ctor.

    o All source files now contain a license and copyright statement
      somewhere within them.

    o Optimized mysql++.h a bit: it now #includes only the minimum set
      of files required, and there is now an idempotency guard.
      This improves compile times a smidge, but mainly it was
      done to clean up the generated #include file graph in the
      reference manual.  Before, it was a frightful tangle because
      we #included everything except custom*.h.

    o Constness fix in MySQL++ date/time classes to avoid compiler
      warnings with SSQLS.  Thanks to Wolfram Arnold for this patch.

    o Fixed some compiler warnings in custom*.h.  Thanks to Chris Frey
      for this patch.

    o Added "Submitting Patches" and "Maintaining a Private CVS
      Repository" sections to the HACKERS file.  Thanks to Chris
      Frey for the source material for these sections.  The HACKERS
      file was improved in several other ways at the same time.

    o PDF version of user manual no longer has links to the reference
      manual.  They were ugly, and they were broken anyway due to the
      way we move the PDFs after generating them.  If you want
      interlinked manuals, use the HTML version.

    o PDF version of user manual now has hard page breaks between
      chapters.

    o Removed complic1 example.  Wasn't pulling its own weight.
      Everything it is supposed to demonstrate is shown in other
      examples already.

    o Refactored print_stock_table() in examples/util module to be
      four functions, and made all the examples use various of
      these functions where appropriate.  Before, several of
      the examples had one-off stock table printing code because
      print_stock_table() wasn't exactly the right thing, for one
      reason or another.  One practical problem with this is that
      some of the examples missed out on the recent Unicode updates;
      now such a change affects all examples the same way.

    o Since so many of the examples rely on the util module, the user
      manual now covers it.  The simple1 example in the user manual
      didn't make much sense before, in particular, because it's
      really just a driver for the util module.

    o Added custom5 example.  It shows how to use the equal_list()
      functionality of SSQLS.  Thanks to Chris Frey for the original
      version of this program.  (I simplified it quite a bit after
      accepting it.)

    o New user manual now covers the value_list(), equal_list() and
      field_list() stuff that the old manual covered but which was
      left out in previous versions of the new manaul.  Most of the
      examples are the same, but the prose is almost completely new.
      This new section includes the custom5 example.

    o Every declaration in MySQL++ is now documented in the reference
      manual, or explicitly treated as "internal only".

    o Improved docs for MySQL++'s mechanism to map between MySQL
      server types and C++ types.  Initial doc patch by Chris Frey,
      which I greatly reworked.

    o Improved a lot of existing reference manual documentation while
      adding the new stuff.

    o Expanded greatly on the exception handling discussion in the user
      manual.

    o Added all-new "Quoting and Escaping" section to the user
      manual's Tutorial chapter.  Moved some existing comments on
      quoting and escaping around and added some new ones to other
      sections as a result.

    o Added all-new "Handling SQL Nulls" section to the user manual's
      Tutorial chapter.

    o Many improvements to the Overview section of the user manual.

    o Row::operator[] reference now explains the right and wrong way to
      use the values it returns.  This is in response to a mailing list
      post where someone was incorrectly using this feature and getting
      a bunch of dangling pointers.

    o Updated Doxyfile so 1.3.19.1 parses it without warnings.  Still
      works with versions back to 1.2.18, at least.  (These are
      the versions shipped with Fedora Core 3 and Red Hat Linux 9,
      respectively.)

    o Using a superior method to make Doxygen ignore certain sections
      of the source code.  Between this change and the fact that
      everything not so ignored is documented, Doxygen no longer
      generates any warnings.

    o Lots of code style updates.  Everything should now be consistently
      formatted.


1.7.35, 2005.05.05 (r601) The "Cinco de Mayo" release

    o Added a "how to use Unicode with MySQL++" chapter to the user
      manual.  (Too bad "Cinco de Mayo" doesn't have any accented
      characters.  That would be just _too_ precious.)

    o VC++ examples now use the Unicode Win32 APIs, so they can display
      Unicode data from MySQL++.

    o Added an optional conversion function to examples/util.cpp to
      handle the conversion from UTF-8 to UCS-2 on Win32.

    o Moved "brief history of MySQL++" from intro section of refman to
      intro section of userman.

    o Lots of small bits of documentation polishing.
    
    o Made some minor constness fixes.  Thanks to Erwin van Eijk
      for this patch.

    o Made some warning fixes for GCC 4.0.  Not all warnings are
      fixed, because some of the needed changes would break the ABI.
      Thanks to Chris Frey for this patch.

    o Added lib/Doxyfile to distribution.
    

1.7.34, 2005.04.30 (r573)

    o Added a multiple-insert method for Query, which lets you insert
      a range of records from an STL container (or the whole thing,
      if you like) in a single SQL query.  This is faster, and it
      reduces coding errors due to less repetition.  Thanks to Mark
      Meredino for the patch.

    o Reference and user manual now get rebuilt automatically when
      required.  (E.g. on 'make dist', or explicitly now through 'make
      docs'.)

    o Made it easier to change the maximum number of SSQLS data members
      in generated custom-macros.h file.  It used to be hard-coded in
      several places in lib/custom.pl; now it's a variable at the top of
      the file.

    o Changed default SSQLS data member limit to 25, which is what it
      has been documented as for a long time now.  It was actually 26
      within custom.pl.

    o Fixed a regression in previous version.

    o Trimmed some fat from the distribution packages.

    o Some more small doucmentation improvements.


1.7.33, 2005.04.29 (r555)

    o Worked around an overloaded operator lookup bug in VC++ 7.1
      that caused SSQLS insert, replace and update queries to get
      mangled.  (Symptom was that custom2 and custom3 examples didn't
      work right.)  Thanks to Mark Meredino for digging up the
      following, which explains the problem and gives the solution:

      http://groups-beta.google.com/group/microsoft.public.vc.stl/browse_thread/thread/9a68d84644e64f15

    o Some VC++ warning fixes.

    o Major documentation improvements:
    
        o Using DocBook for user manual and Doxygen for reference
          manual.  The former now references the latter where
          useful.

        o Split out HACKERS and CREDITS files from main README,
          and improved remaining bits of README.

        o Moved the text from the old v1.7.9 LaTeX-based
          documentation over into the new systems, and reworked
          it to more closely resemble English.

        o Added a lot of new material to documentation, and
          simplified a lot of what already existed.

        o Documentation is now being built in HTML and PDF forms.

    o ebuild file updated to take advantage of recent configure script
      features.  Thanks to Chris Frey for this patch.



1.7.32, 2005.03.10 (r479)

    o Example building may now be skipped with --disable-examples
      configure script flag.

    o Changed stock items added in resetdb.  One is now UTF-8 encoded,
      to show that basic use of Unicode with MySQL++ is easy, yet not
      foolproof.  (See formatting of table on systems where cout isn't
      UTF-8 aware!)  Other stock items now follow a theme, for your
      amusement.  :)

    o custom3 example now changes UTF-8 item's name to the 7-bit ASCII
      equivalent.  Previously, this example would fix a spelling error
      in the table.

    o resetdb example now says 'why' when it is unable to create the
      sample database.

    o Small formatting change to print_stock_table(), used by several
      examples.

    o Was issuing a VC++-specific warning-disable pragma when built by
      any Windows compiler.  Fixed.
    

1.7.31, 2005.03.05 (r462) The "Inevitable Point-one Followup" release

    o Check for threads support must now be explicitly requested via
      configure script's new --enable-thread-check flag.

    o Fix for contacting MySQL server on a nonstandard port number.
      Thanks to Chris Frey for this patch.

    o Example programs using standard command line format now accept a
      fourth optional parameter, a port number for the server.  Thanks
      to Chris Frey for this patch.

    o One more g++ 3.4 pedantic warning fix by Chris Frey.

    o Exception handling in resetdb is no longer nested, because you'd
      get a segfault on some systems when an exception was thrown from
      one of the inner try blocks.

    o Improvements to Connection class's handling of locking mechanism.
      Concept based on patches by Rongjun Mu.

    o Implemented the declared-but-never-defined Query::lock().  Thanks
      to Rongjun Mu for this patch.
    
    o Cleaned up some unclear if/else blocks in connection.cpp by
      adding explicit braces, correct indenting and putting normal
      code path in the if side instead of the else.


1.7.30, 2005.02.28 (r443) The "Power of Round Numbers" release

    o bootstrap script now accepts a 'pedantic' argument, which sets a
      bunch of CFLAGS that make g++ very picky about the code it
      accepts without warnings.
      
    o Fixed a bunch of things that generated warnings with g++ in
      pedantic mode. Only two warnings remain, having to do with
      floating point comparisons.  (See Wishlist for plans on how to
      deal with these.)  Thanks to Chris Frey for this patch.

    o Split long tests out of configure.in into M4 files in new config
      subdir.  This makes configure.in easier to read.

    o Added preliminary thread support.  Currently, this just means that
      we detect the required compiler and linker thread flags, and link
      against the proper thread-safe libraries.  THERE MAY BE
      UN-THREAD-SAFE CODE IN MYSQL++ STILL!

    o Standard C++ exceptions are the default now.  Old pre-Standard
      exception stuff removed.

    o Row::lookup_by_name() will throw the new BadFieldName exception if
      you pass a bad field name.  Thanks for this patch to Chris Frey.

    o Row::operator[] will throw a Standard C++ out of bounds exception
      by way of std::vector::at() if you pass it a bad index.  Thanks
      for this patch to Chris Frey.

    o Setting Connection::is_connected flag to false on close().
      Previously, is_connected() would continue to return true after
      close() was called.

    o All number-to-string conversion ctors in SQLString class now use
      ostringstream to do the conversion.  Previously, we used
      snprintf(), which isn't available on all systems.  Also, we used a
      C99 format specifier for the "long long" conversion, which is also
      not available on all systems.  This new ostringstream code should
      be platform-independent, finally.


1.7.28, 2005.02.04 (r403)

    o --with-mysql* flags to configure script now try the given
      directory explicitly, and only if that fails do they try
      variations, like tacking '/lib' and such onto it to try and find
      the MySQL includes and libraries.  Thanks to Matthew Walton for
      the patch.

    o Finally removed sql_quote.h's dependence on custom.h, by moving
      the one definition it needed from custom.h to deps.h.  This will
      help portability to compilers that can't handle the SSQLS macros,
      by making that part of the library truly optional.


1.7.27, 2005.01.12 (r395)

    o configure check for libmysqlclient now halts configuration if the
      library isn't found.  Previously, it would just be flagged as
      missing, and MySQL++ would fail to build.

    o Added sql_string.cpp to VC++ and BCBuilder project files.

    o Removed Totte Karlsson's 'populate' example, which never made it
      into the distribution anyway.

    o Removed last vestiges of 'dummy.cpp'.

    o Renamed *.cc to *.cpp in BCBuilder project files.

    o Worked around a BCBuilder C++ syntax processing bug in row.h.


1.7.26, 2004.12.17 (r382)

    o Moved all of the SQLString definitions out of the header and into
      a new .cpp file, reformatted it all, and made the integer
      conversion functions use snprintf() or _snprintf() instead of
      sprintf().  Also, widened some of the buffers for 64-bit systems.

    o Using quoted #include form for internal library headers, to avoid
      some problems with file name clashes.  (The headers should still
      be installed in their own separate directory for best results,
      however.)  Thanks to Chris Frey and Evan Wies for the patch and
      the discussion that lead to it.

    o Removed unnecessary semicolons on namespace block closures.
      Thanks to Evan Wies for this patch.

    o Fixed namespace handling in the legacy headers mysql++.hh and
      sqlplus.hh.  Thanks to Chris Frey for this patch.

    o #including iostream instead of ostream in lib/null.h for
      broader C++ compatibility.  (This may allow MySQL++ to work on GCC
      2.95.2 again, but this is unconfirmed.)

    o Detecting proper mysql_shutdown() argument handling automatically
      in platform.h for the Windows compiler case instead of making the
      user edit the file.  Thanks to Evan Wies for this patch.
    
    o Fixed examples/Makefile.simple to use new *.cpp file naming.

    o Fix to Gentoo ebuild file's exception configure switch handling.
      Thanks to Chris Frey for this patch.

    o Rebuilding lib/custom*.h intelligently now, to avoid unnecessary
      recompiles after running bootstrap script.


1.7.25, 2004.12.09 (r360)

    o Yet more fixes to the --with-mysql-lib and --with-mysql-include
      flags.

    o Added DLLEXPORT stuff to platform.h, hopefully so that someone
      can figure out how to make VC++ make a DLL version of MySQL++.

    o Renamed *.cc to *.cpp.

    o Made 'set -> myset' change in VC++ project files.

    o Some style changes (mostly whitespace) in header files.


1.7.24, 2004.12.08 (r343)

    o Fixed the --with-mysql-lib and --with-mysql-include flags'
      behavior, and extended their search ability to handle one other
      common case.  (Fixed by Steve Roberts)

    o Fixes to put freestanding functions in namespace mysqlpp.  (They
      weren't in the namespace, while all the class member functions
      were.)  This required bumping the ABI version number to 4.
      
    o Renamed set module to myset, to avoid conflicts with Standard C++
      Library's set.h when MySQL++ headers were installed into one of
      the standard system include directories.

    o Renamed all the idempotency guards to make them consistent in
      style and unique to MySQL++.

    o Reformatted all of lib/*.cc.


1.7.23, 2004.11.20 (r333)

    o Query::reset() now empties the stored query string.  If you
      subsequently stored a longer query in the object, you'd overwrite
      the previous query, but otherwise the longer part of the previous
      one would stick out past the new query.

    o We now look to the NO_LONG_LONGS macro only to decide whether to
      fake 64-bit integer support using 32-bit integers.

    o 64-bit integer support under Visual C++ may be working now, using
      that platform's __int64_t type.  This has not been tested.

    o Removed 64-bit integer support for Codewarrior on Mac OS 9 and
      earlier.  OS X uses GCC, so it requires no special support.

    o Added MinGW detection in platform.h.
    
    o If you pass a flag (-X) to the examples that take the standard
      parameters (resetdb, simple1, etc.), it prints a usage message.
    
    o Better error handling in resetdb example, where errors are the
      most critical.  (If that one runs without errors, the others
      probably will, too, and you have to run that one first.)

    o resetdb now reports success, rather than succeeding silently.

    o Removed the code in sample1 example that duplicated util module's
      print_stock_table(), and called that function instead.

    o Moved the preview() calls in the example programs to before the
      query execution calls, because execution modifies the query.

    o All examples that take the standard command line parameters now 
      exit when connect_to_db() fails in one of the ways that don't
      throw an exception, rather than bulling onward until the next
      MySQL database call fails because the connection isn't up.

    o dbinfo example now takes the standard command line parameters.

    o Much better output formatting in dbinfo example.

    o Calling reset() where appropriate in the various example programs.
      Before, the programs may have worked, but not for the right
      reason.  This lead some people to believe that calling reset()
      was not necessary.

    o Fixed an incorrect use of row["string"] in complic1 example.

    o Lots of code style improvements to the examples.

    o Some VC++ type warnings squished.  Some remain.
    

1.7.22, 2004.11.17 (r302)

    o Applied patches by Zahroof Mohammed to allow it to build under GCC
      3.4.2.  Tested on MinGW and Fedora Core 3 systems.

    o Removed all the forward declarations in defs.h, and added
      forward declarations where necessary in individual header files.
      #including defs.h in fewer locations as a result.

    o Legacy headers sqlplus.hh and mysql++.hh now declare they are
      using namespace mysqlpp, to allow old code to compile against the
      new library without changes.

    o Removed query_reset parameter from several class Query member
      functions.  In the implementation, these parameters were always
      overridden!  No sense pretending that we pay attention to these
      parameters.  This changes the ABI version to 3.

    o #including custom.h in sql_query.h again...it's necessary on GCC
      3.4.
    
    o bootstrap script runs lib/config.pl after configure.  This is
      just a nicety for those running in 'maintainer mode'.


1.7.21, 2004.11.05 (r273)

    o Generating a main mysql++ RPM containing just the library files
      and basic documentation, and the -devel package containing
      everything else.

    o Devel package contains examples now, along with a new Makefile
      that uses the system include and library files, rather than the
      automake-based Makefile.am we currently have which uses the files
      in the mysql++ source directory.

    o Renamed sqlplusint subdirectory in the package to lib.

    o Removed the obsolete lib/README file.

    o lib/sql_query.h no longer #includes custom.h, simplifying
      build-time dependencies and shortening compile times.


1.7.20, 2004.11.03 (r258)

    o Collapsed all numbered *.hh headers into a single *.h file.  For
      example, the contents of row1.hh, row2.hh and row3.hh are now in
      row.h.

    o While doing the previous change, broke several circular
      dependencies.  (The numbered file scheme was probably partly done
      to avoid this problem.)  The practical upshot of most of these
      changes is that some functions are no longer inline.

    o Removed define_short.hh and everything associated with it.  The
      library now uses the short names exclusively (e.g. Row instead of
      MysqlRow).

    o Put all definitions into namespace mysqlpp.  For most programs,
      simply adding a 'using namespace mysqlpp' near the top of the
      program will suffice to convert to this version.

    o Once again, the main include file was renamed, this time to
      mysql++.h.  Hopefully this is the last renaming!

    o mysql++.hh still exists.  It emits a compiler warning that the
      file is obsolete, then it #includes mysql++.h for you.

    o sqlplus.hh is back, being a copy of the new mysql++.hh.  Both of
      these files may go away at any time.  They exist simply to help
      people transition to the new file naming scheme.

    o Renamed mysql++-windows.hh to platform.h, and added code to it to
      handle #inclusion of config.h on autotools-based systems
      intelligently.  This fixes the config.h error when building under
      Visual C++.

    o There is now only one place where conditional inclusion of
      winsock.h happens: platform.h.

    o Beautified the example programs.


1.7.19, 2004.10.25 (r186)

    o Fixed an infinite loop in the query mechanism resulting from the
      strstream change in the previous version.  There is an overloaded
      set of str() member functions that weren't a problem when query
      objects were based on strstream.
     
    o Query mechanism had a bunch of const-incorrectness: there were
      several function parameters and functions that were const for
      the convenience of other parts of the code, but within these
      functions the constness was const_cast away!  This was evil
      and wrong; now there are fewer const promises, and only one is
      still quietly broken within the code.  (It's in the SQLQuery
      copy ctor implementation; it should be harmless.)

    o Removed operator=() in Query and SQLQuery classes.  It cannot take
      a const argument for the same reason we have to cast away const
      in the SQLQuery copy ctor.  It's tolerable to do this in the copy
      ctor, but intolerable in an operator.  Since the copy ctor is good
      enough for all code within the library and within my own code, I'm
      removing the operator.

    o Above changes required bumping the ABI to version 2.

    o Visual C++ projects now look for MySQL build files in c:\mysql,
      since that's the default install location.  (Previously, it was
      c:\program files\mysql.)


1.7.18, 2004.10.01 (r177)

    o Changed all the strstream (and friends) stuff to stringstream type
      classes.  Let there be much rejoicing.

    o Query object now lets you use store() even when the SQL query
      cannot return a result, such as a DROP TABLE command.  This is
      useful for sending arbitrary SQL to the server.  Thanks to
      Jose Mortensen for the patch.

    o Quote fix in configure.in, thanks to David Sward.

    o Renamed undef_short file to undef_short.hh.

    o Gentoo ebuild file is actually being shipped with the tarball,
      instead of just sitting in my private CVS tree since 1.7.14 was
      current.  Ooops....


1.7.17, 2004.09.16 (r170)

    o Reverted one of the VC++ warning fix changes from 1.7.16 that
      caused crashes on Linux.

    o Added a configure test that conditionally adds the extra 'level'
      parameter to mysql_shutdown() that was added in MySQL 4.1.3 and
      5.0.1.


1.7.16, 2004.09.13 (r160)

    o Building VC++ version with DLL version of C runtime libraries, and
      at warning level 3 with no warnings emitted.

    o VC++ build no longer attempts to fake "long long" support.  See
      the Wishlist for further thoughts on this.


1.7.15, 2004.09.02 (r144)

    o Renamed Configure file to common.am, to avoid file name conflict
      with configure script on case-sensitive file systems.

    o Added ebuild file and ebuild target to top-level Makefile for
      Gentoo systems.  Thanks to Chris Frey for this.

    o Small efficiency improvements to BadQuery exception handling.
      Initial idea by Chris Frey, improvements by Warren Young.


1.7.14, 2004.08.26 (r130)

    o Builds with Visual C++ 7.1.

    o Fixed a bug in custom macro generation that caused problems with
      GCC 3.4.  (X_cus_value_list ctor definition was broken.)


1.7.13, 2004.08.23 (r92)

    o Removed USL CC support.  (System V stock system compiler.)  Use
      GCC on these platforms instead.

    o Added examples/README, explaining how to use the examples, and
      what they all do.

    o Most of the example programs now accept command line arguments for
      host name, user name and password, like resetdb does.

    o Renamed sinisa_ex example to dbinfo.

    o Several Standard C++ syntax fixes to quash errors emitted by
      GCC 3.4 and Borland C++ Builder 6.  Thanks to Steffen Schumacher
      and Totte Karlsson for their testing and help with these.

    o Added proper #includes for BCBuilder, plus project files for same.
      Thanks to Totte Karlsson for these.


1.7.12, 2004.08.19 (r63)

    o Many Standard C++ fixes, most from the GCC 3.4 patch by
      Rune Kleveland.

    o Added Wishlist file to distribution.

    o Fixed a problem in the bootstrap script that caused complaints
      from the autotools on some systems.

    o RPM building is working properly now.

    o Fixed the idempotency guard in datetime1.hh.


1.7.11, 2004.08.17 (r50)

    o Renamed mysql++, defs and define_short files, adding .hh to the
      end of each.  (They're header files!)  This shouldn't impact
      library users, since these are hopefully used internal to the
      library only.

    o Removed sqlplus.hh file.  Use mysql++.hh instead.
    
    o Added mysql++.spec, extracted from contributed 1.7.9 source RPM, 
      and updated it significantly.  Also, added an 'rpm' target to
      Makefile.am to automate the process of building RPMs.

    o Added bootstrap and LGPL files to distribution tarball.

    o Added pre-1.7.10 history to this file.

    o Removed .version file.  Apparently it's something required by old
      versions of libtool.


1.7.10, 2004.08.16 (r27)

    o Maintenance taken over by Warren Young (mysqlpp at etr dash usa
      dot com.) See http://lists.mysql.com/plusplus/3326 for details.

    o Applied many of the GCC 3.x patches submitted for 1.7.9 over
      the years.  This allows it to build on everything from 3.0 to
      3.3.3, at least.  Because so many patches are rolled up in one
      big jump, it's difficult to describe all the changes and where
      they came from.  Mostly they're Standard C++ fixes, as GCC
      has become more strict in the source code that it will accept.

    o MysqlRow used to overload operator[] for string types as well as
      integers so you could look up a field by its name, rather than by
      its index.  GCC 3.3 says this is illegal C++ due to ambiguities in
      resolving which overload should be used in various situations.
      operator[] is now overloaded only for one integer type, and a
      new member function lookup_by_name() was added to maintain the old
      by-field-name functionality.

    o Fixed another operator overloading problem in SSQLS macro
      generation with GCC 3.3.

    o The _table member of SSQLS-defined structures is now const char*,
      so you can assign to it from a const char* string.

    o Got autoconf/automake build system working with current versions
      of those tools again.  Removed the generated autotools files from
      CVS.

    o Renamed library file from libsqlplus to libmysqlpp.


1.7.9 (May 1 2001) Sinisa Milivojevic <sinisa@mysql.com>

    * Fixed a serious bug in Connection constructor when reading MySQL
    * options
    * Improved copy constructor and some other methods in Result /
    * ResUse
    * Many other minor improvements
    * Produced a complete manual with chapter 5 included
    * Updated documentation, including a Postscript format

1.7.8 (November 14 2000) Sinisa Milivojevic <sinisa@mysql.com>

    * Introduced a new, standard way of dealing with C++ exceptions.
    * MySQL++ now supports two different methods of tracing exceptions.
    * One is by the fixed type (the old one) and one is standard C++
    * type by the usage of what() method. A choice of methods has to be
    * done in building a library. If configure script is run with
    * -enable-exception option , then new method will be used. If no
    * option is provided, or -disable-exception is used, old MySQL++
    * exceptions will be enforced. This innovation is a contribution of
    * Mr. Ben Johnson <ben@blarg.net>
    * MySQL++ now automatically reads at connection all standard MySQL
    * configuration files
    * Fixed a bug in sql_query::parse to enable it to parse more then 99
    * char's
    * Added an optional client flag in connect, which will enable usage
    * of this option, e.g. for getting matched and not just affected
    * rows. This change does not require any changes in existing
    * programs
    * Fixed some smaller bugs
    * Added better handling of NULL's. Programmers will get a NULL
    * string in result set and should use is_null() method in ColData to
    * check if value is NULL
    * Further improved configuration
    * Updated documentation, including a Postscript format

1.7.6 (September 22 2000) Sinisa Milivojevic <sinisa@mysql.com>

    * This release contains some C++ coherency improvements and scripts
    * enhacements
    * result_id() is made available to programmers to fetch
    * LAST_INSERT_ID() value
    * Connection constroctur ambiguity resolved, thanks to marc@mit.edu
    * Improved cnnfigure for better finding out MySQL libraries and
    * includes
    * Updated documentation, including a Postscript format

1.7.5 (July 30 2000) Sinisa Milivojevic <sinisa@mysql.com>

    * This release has mainl bug fixes  and code improvements
    * A bug in FieldNames::init has been fixed, enabling a bug free
    * usage of this class with in what ever a mixture of cases that is
    * required
    * Changed behaviour of ResUse, Result and Row classes, so that they
    * could be re-used as much as necessary, without any memory leaks,
    * nor with any re-initializations necessary
    * Fixed all potential leaks that could have been caused by usage of
    * delete instead of delete[] after memory has been allocated with
    * new[]
    * Deleted all unused classes and macros. This led to a reduction of
    * library size to one half of the original size. This has
    * furthermore brought improvements in compilation speed
    * Moved all string manipulation from system libraries to
    * libmysqlclient, thus enabling uniformity of code and usage of 64
    * bit integers on all platforms, including Windows, without
    * reverting to conditional compilation. This changes now requires
    * usage of mysql 3.23 client libraries, as mandatory
    * Changed examples to reflect above changes
    * Configuration scripts have been largely changed and further
    * changes shall appear in consecutive sub-releases. This changes
    * have been done and shall be done by our MySQL developer Thimble
    * Smith <tim@mysql.com>
    * Changed README, TODO and text version of manual. Other versions of
    * manual have not been updated
    * Fixed .version ``bug''. This is only partially fixed and version
    * remains 1.7.0 due to some problems in current versions of libtool.
    * This shall be finally fixed in a near future
    * Several smaller fixes and improvements
    * Added build.sh script to point to the correct procedure of
    * building of this library. Edit it to add configure options of your
    * choice

1.7 (May17 2000) Sinisa Milivojevic <sinisa@mysql.com>

    * This is mainly a release dealing with bug fixes, consistency
    * improvements and easier configure on some platforms
    * A bug in fetch_row() method of ResUse class has been fixed. Beside
    * changes that existed in a distributed patch, some additional error
    * checking has been introduced
    * A bug in escape manipulator has been fixed that could cause an
    * error if all characters had to be escaped
    * An inconsistency in column indexing has been fixed. Before this
    * version, column names in row indexing with strings, i.e.
    * row[<string>] , has been case sensitive, which was inconsistent
    * with MySQL server handling of column names
    * An inconsistency in conversion from strings to integers or floats
    * has been fixed. In prior version a space found in data would cause
    * a BadConversion exception. This has been fixed, but 100%
    * consistency with MySQL server has not been targeted, so that other
    * non-numeric characters in data will still cause BadConversion
    * exception or error. As this API is used in applications, users
    * should provide feedback if full compatibility with MySQL server is
    * desired, in which case BadConversion exception or error would be
    * abolished in some of future versions
    * A new method in ColData class has been introduced. is_null()
    * method returns a boolean to denote if a column in a row is NULL.
    * Finally, as of this release, testing for NULL values is possible.
    * Those are columns with empty strings for which is_null() returns
    * true.
    * Some SPARC Solaris installations had C++ exception problems with
    * g++ 2.95.2 This was a bug that was fixed in GNU gcc, as from
    * release 2.95 19990728. This version was thoroughly tested and is
    * fully functional on SPARC Solaris 2.6 with the above version of
    * gcc.
    * A 'virtual destructor ' warning for Result class has been fixed
    * Several new functions for STL strings have been added. Those
    * functions (see string_util.hh) add some of the functionality
    * missing in existing STL libraries
    * Conversion for 64 bit integers on FreeBSD systems has been added.
    * On those systems _FIX_FOR_BSD_ should be defined in CXXFLAGS prior
    * to configuring. Complete conversion to the usage of functions for
    * integer conversion found in mysqlclient library is planned for one
    * of the next releases
    * A completely new, fully dynamic, dramatic and fully mutable result
    * set has been designed and will be implemented in some of 2.x
    * releases
    * Several smaller fixes and improvements, including defaulting
    * exceptions to true, instead of false, as of this version
    * An up-to-date and complete Postscript version of documentation is
    * included in this distribution
    * Large chunks of this manual are changed, as well as README and
    * TODO files.

1.6 (Feb 3 2000) Sinisa Milivojevic <sinisa@mysql.com>

    * This is a major release as it includes new features and major
    * rewrites
    * Automatic quoting and escaping with streams. It works
    * automatically , depending on the column type. It will work with <<
    * on all ostream derived types. it is paricularly handy with query
    * objects and strstreams. Automatic quoting and escaping on cout,
    * cerr and clog stream objects is intentionally left out, as quoting
    * / escaping on those stream objects is not necessary. This feature
    * can be turned of by setting global boolean dont_quote_auto to
    * true.
    * Made some major changes in code, so that now execute method should
    * be used only with SSQL and template queries, while for all other
    * query execution of UPDATE's, INSERT's, DELETE's, new method exec()
    * should be used. It is also faster.
    * New method get_string is inroduced for easier handling / casting
    * ColData into C++ strings.
    * Major rewrite of entire code, which led to it's reduction and
    * speed improvement. This also led to removal of several source
    * files.
    * Handling of binary data is introduced. No application program
    * changes are required. One of new example programs demonstrates
    * handling of binary data
    * Three new example programs have been written and thoroughly
    * tested. Their intention is to solve some problems addressed by
    * MySQL users.
    * Thorough changes is Makefile system has been made
    * Better configuration scripts are written, thanks to D.Hawkins
    * <dhawkins@cdrgts.com>
    * Added several bug fixes
    * Changed Manual and Changelog

1.5 (Dec 1 1999) Sinisa Milivojevic <sinisa@mysql.com>

    * Fixed bug in template queries, introduced in 1.4 (!)
    * Fixed connect bug
    * Fixed several bug in type_info classes
    * Added additional robustness in classes
    * Added additional methods for SQL type info
    * Changed Changelog and README

1.4 (Nov 25 1999) Sinisa Milivojevic <sinisa@mysql.com>

    * Fixed bug in store and storein methods
    * Fixed one serious memory leak
    * Fixed a very serious bug generated by gcc 2.95.xx !!
    * Added robustness in classes, so that e.g. same query and row
    * objects can be re-used
    * Changed sinisa_ex example to reflect and demonstrate this
    * stability
    * Changed Changelog and README
    * Few other bug fixes and small improvements and speed-ups

1.3 (Nov 10 1999) Sinisa Milivojevic <sinisa@mysql.com>

    * Fixed several erronous definitions
    * Further changed source to be 2.95.2 compatible
    * Expunged unused statements, especially dubious ones, like use of
    * pointer_tracker
    * Corrected bug in example file fieldinf1
    * Finally fixed mysql_init in Connection constructor, which provided
    * much greater stability !
    * Added read and get options, so that clients, like mysqlgui can use
    * it
    * Changed Changelog and README
    * Many other bug fixes.

1.2 (Oct 15 1999) Sinisa Milivojevic <sinisa@mysql.com>

    * First offical release. Version 1.0 and 1.1 were releases by Sinisa
    * before I (Kevin Atkinson) made him the offical maintainer,
    * Many manual fixes.
    * Changed README and Changelog
    * Changed source to be compilable by gcc 2.95.xx, tribute to Kevin
    * Atkinson <kevinatk@home.com>
    * Added methods in Connection class which are necessary for
    * fullfilling administrative functions with MySQL
    * Added many bug fixes in code pertaining to missing class
    * initializers , as notified by Michael Rendell <michael@cs.mun.ca>
    * Sinisa Milivojevic <sinisa@mysql.com> is now the offical
    * maintainer.

1.1 (Aug 2 1999) Sinisa Milivojevic <sinisa@mysql.com>

    * Added several bug fixes
    * Fixed memory leak problems and variables overlapping problems.
    * Added automake and autoconf support by loic@ceic.com
    * Added Makefile for manual
    * Added support for cygwin
    * Added example sinisa_ex (let modesty prevail) which used to crash
    * a lot when memory allocation, memory leak and overlap problems
    * were present. Smooth running of this example proves that all those
    * bugs are fixed
    * Corrected bugs in sql_query.cc regarding delete versus delete[]
    * and string length in manip.cc
    * Changed manual
    * Changed README
    * Many other smaller things

1.0 (June 9 1999) Michael Widenius <monty@monty.pp.sci.fi>

    * Added patches from Orion Poplawski <orion@bvt.com> to support the
    * UnixWare 7.0 compiler

.64.1.1a (Sep 27 1998)

    * Fixed several bugs that caused my library to fail to compile with
    * egcs 1.1. Hopefully it will still compile with egcs 1.0 however I
    * have not been able to test it with egcs 1.0.
    * Removed some problem causing debug output in sql++pretty.

.64.1a (Aug 1 1998)

    * Added an (almost) full guide to using Template Queries.
    * Fixed it so the SQLQuery will throw an exception when all the
    * template parameters are not provided.
    * Proofread and speedchecked the manual (it really needed it).
    * Other minor document fixes.

.64.0.1a (July 31 1998)

    * Reworked the Class Reference section a bit.
    * Minor document fixes
    * Added more examples for SSQLS.
    * Changed the syntax of equal_list for SSQLS from equal_list (cchar
    * *, Manip, cchar *) to (cchar *, cchar *, Manip).
    * Added set methods to SSQLS. These new methods do the same thing as
    * there corresponding constructors.
    * Added methods for creating a mysql_type_info from a C++ type_info.

.64.a (July 24 1998)

    * Changed the names of all the classes so they no longer have to
    * have Mysql in the begging of it. However if this creates a problem
    * you can define a macro to only use the old names instead.
    * The Specialized SQL Structures (formally known as Custom Mysql
    * Structures) changed from mysql_ to sql_.
    * Added the option of using exceptions thoughout the API.
    * ColData (formally known as MysqlStrings) will now throw an
    * exception if there is a problem in the conversion.
    * Added a null adapter.
    * Added Mutable Result Sets
    * Added a very basic runtime type identification for SQL types
    * Changed the document format from POD to LYX .
    * Am now using a modified version of Perceps to extract the class
    * information directly from the code to make my life easier.
    * Added an option of defining a macro to avoid using the automatic
    * conversion with binary operators.
    * Other small fixed I probully forgot to mentune.

.63.1.a

    * Added Custom Mysql Structures.
    * Fixed the Copy constructor of class Mysql
    * Started adding code so that class Mysql lets it children now when
    * it is leaving
    * Attempted to compile it into a library but still need help. As
    * default it will compile as a regular program.
    * Other small fixes.

.62.a (May 3 1998)

    * Added Template Queries
    * Created s separate SQLQuery object that is independent of an SQL
    * connection.
    * You no longer have to import the data for the test program as the
    * program creates the database and tables it needs.
    * Many small bug fixes.

.61.1.a (April 28 1998)

    * Cleaned up the example code in test.cc and included it in the
    * manual.
    * Added an interface layout plan to the manual.
    * Added a reverse iterator.
    * Fixed a bug with row.hh (It wasn't being included because of a
    * typo).

.61.0.a

    * Major interface changes. I warned you that the interface may
    * change while it is in pre-alpha state and I wasn't kidding.
    * Created a new and Separate Query Object. You can no longer execute
    * queries from the Mysql object instead you have to create a query
    * object with Mysql::query() and use it to execute queries.
    * Added the comparison operators to MysqlDate, MysqlTime and
    * MysqlDateTime. Fixed a few bugs in the MysqlDate... that effected
    * the stream output and the conversion of them to strings.
    * Reflected the MysqlDate... changes in the manual.
    * Added a new MysqlSet object and a bunch of functions for working
    * with mysql set strings.

.60.3a (April 24 1998)

    * Changed strtoq and strtouq to strtoll and strtull for metter
    * compatibility Minor Manual fix.
    * Changed makefile to make it more compatible with Solaris (Thanks
    * Chris H)
    * Fixed bug in comparison functions so that they would compare in he
    * right direction.
    * Added some items to the to do list be sure to have a look.

Changes to test/inttypes.cpp.

1

2
3



4








5
6
7
8
9
10

11












12
13
14
15


16
17
18




19

20
21
22
23
24
25










26




27



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
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71



72
73
74



75
76



77




78
/***********************************************************************

 test/inttypes.cpp - Tests whether the integer typedef equivalents for
	SQL types in lib/sql_types.h are correct on this system.  If not,



	you need to change either that file, lib/common.h, or both.









 Copyright (c) 2008 by Educational Technology Resources, Inc.
 Others may also hold copyrights on code in this file.  See the
 CREDITS.txt file in the top directory of the distribution for details.

 This file is part of MySQL++.














 MySQL++ is free software; you can redistribute it and/or modify it
 under the terms of the GNU Lesser General Public License as published
 by the Free Software Foundation; either version 2.1 of the License, or
 (at your option) any later version.



 MySQL++ is distributed in the hope that it will be useful, but WITHOUT
 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or




 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public

 License for more details.

 You should have received a copy of the GNU Lesser General Public
 License along with MySQL++; if not, write to the Free Software
 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
 USA










***********************************************************************/








#include <sql_types.h>

#include <iostream>

template <typename IntType>
static bool
test_size(const char* desc, IntType value, size_t expected_size)
{
	size_t actual_size = sizeof(value);
	if (actual_size == expected_size) {
		return true;
	}
	else {
		std::cerr << desc << " is sized incorrectly on this "
				"platform:" << std::endl << "\t" << actual_size <<
				" bytes, not " << expected_size << " as expected." <<


				std::endl;


		return false;

	}
}








int

main()


{




	int failures = 0;





	failures += test_size("sql_tinyint",
			mysqlpp::sql_tinyint(0), 1) == false;
	failures += test_size("sql_tinyint_unsigned",
			mysqlpp::sql_tinyint_unsigned(0), 1) == false;
	failures += test_size("sql_smallint",
			mysqlpp::sql_smallint(0), 2) == false;
	failures += test_size("sql_smallint_unsigned",
			mysqlpp::sql_smallint_unsigned(0), 2) == false;
	failures += test_size("sql_mediumint",
			mysqlpp::sql_mediumint(0), 4) == false;
	failures += test_size("sql_mediumint_unsigned",
			mysqlpp::sql_mediumint_unsigned(0), 4) == false;
	failures += test_size("sql_int",
			mysqlpp::sql_int(0), 4) == false;
	failures += test_size("sql_int_unsigned",
			mysqlpp::sql_int_unsigned(0), 4) == false;
	failures += test_size("sql_bigint",



			mysqlpp::sql_bigint(0), 8) == false;
	failures += test_size("sql_bigint_unsigned",
			mysqlpp::sql_bigint_unsigned(0), 8) == false;



	
	return failures;



}





<
>
|
|
>
>
>
|
>
>
>
>
>
>
>
>
|
<
<
<
|
<
>
|
>
>
>
>
>
>
>
>
>
>
>
>
|
<
<
<
>
>
|
|
|
>
>
>
>
|
>
|
|
<
|
<
|
>
>
>
>
>
>
>
>
>
>
|
>
>
>
>

>
>
>
|

<
|
<
<
<
|
<
<
<
<
|
<
<
<
>
>
|
>
>
|
>
|
|
|
>
|
>
>
>
>
>
|
>
|
>
>
|
>
>
>
>
|
>
>
>
>

<
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
>
>
>
|
<
|
>
>
>
|
<
>
>
>
|
>
>
>
>


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16



17

18
19
20
21
22
23
24
25
26
27
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
56
57
58
59
60
61
62
63
64
65
66
67
68

69



70




71



72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104

105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124

125
126
127
128
129

130
131
132
133
134
135
136
137
138

dnl @synopsis MYSQL_C_API_LOCATION
dnl 
dnl This macro tries to find MySQL C API header and library locations.
dnl
dnl We define the following configure script flags:
dnl
dnl		--with-mysql: Give prefix for both library and headers, and try
dnl			to guess subdirectory names for each by tacking common
dnl         suffixes on like /lib and /include.
dnl		--with-mysql-lib: Same as --with-mysql, but for library only.
dnl		--with-mysql-include: Same as --with-mysql, but for headers only.
dnl
dnl @version 1.4, 2009/05/28
dnl @author Warren Young <mysqlpp@etr-usa.com>
AC_DEFUN([MYSQL_C_API_LOCATION],
[



	#

	# Set up configure script macros
	#
	AC_ARG_WITH(mysql,
		[  --with-mysql=<path>     root directory path of MySQL installation],
		[MYSQL_lib_check="$with_mysql/lib/mysql $with_mysql/lib"
		MYSQL_inc_check="$with_mysql/include $with_mysql/include/mysql"],
		[MYSQL_lib_check="/usr/lib64 /usr/lib /usr/lib64/mysql /usr/lib/mysql /usr/local/lib64 /usr/local/lib /usr/local/lib/mysql /usr/local/mysql/lib /usr/local/mysql/lib/mysql /usr/mysql/lib/mysql /opt/mysql/lib /opt/mysql/lib/mysql /sw/lib /sw/lib/mysql"
		MYSQL_inc_check="/usr/include/mysql /usr/local/include/mysql /usr/local/mysql/include /usr/local/mysql/include/mysql /usr/mysql/include/mysql /opt/mysql/include/mysql /sw/include/mysql"])
	AC_ARG_WITH(mysql-lib,
		[  --with-mysql-lib=<path> directory path of MySQL library installation],
		[MYSQL_lib_check="$with_mysql_lib $with_mysql_lib/lib64 $with_mysql_lib/lib $with_mysql_lib/lib64/mysql $with_mysql_lib/lib/mysql"])
	AC_ARG_WITH(mysql-include,
		[  --with-mysql-include=<path> directory path of MySQL header installation],
		[MYSQL_inc_check="$with_mysql_include $with_mysql_include/include $with_mysql_include/include/mysql"])




	#
	# Decide which C API library to use, based on thread support
	#
	if test "x$acx_pthread_ok" = xyes
	then
		MYSQL_C_LIB_NAME=mysqlclient_r
	else
		MYSQL_C_LIB_NAME=mysqlclient
	fi

	#
	# Look for MySQL C API library
	#

	AC_MSG_CHECKING([for MySQL library directory])

	MYSQL_C_LIB_DIR=
	for m in $MYSQL_lib_check
	do
		if test -d "$m" && \
			(test -f "$m/lib$MYSQL_C_LIB_NAME.so" || \
			 test -f "$m/lib$MYSQL_C_LIB_NAME.a")
		then
			MYSQL_C_LIB_DIR=$m
			break
		fi
	done

	if test -z "$MYSQL_C_LIB_DIR"
	then
		AC_MSG_ERROR([Didn't find $MYSQL_C_LIB_NAME library in '$MYSQL_lib_check'])
	fi

	case "$MYSQL_C_LIB_DIR" in
		/* ) ;;
		* )  AC_MSG_ERROR([The MySQL library directory ($MYSQL_C_LIB_DIR) must be an absolute path.]) ;;
	esac


	AC_MSG_RESULT([$MYSQL_C_LIB_DIR])








	case "$MYSQL_C_LIB_DIR" in



	  /usr/lib)
		MYSQL_C_LIB_DIR=
	  	;;
	  *)
	  	LDFLAGS="$LDFLAGS -L${MYSQL_C_LIB_DIR}"
		;;
	esac


	#
	# Look for MySQL C API headers
	#
	AC_MSG_CHECKING([for MySQL include directory])
	MYSQL_C_INC_DIR=
	for m in $MYSQL_inc_check
	do
		if test -d "$m" && test -f "$m/mysql.h"
		then
			MYSQL_C_INC_DIR=$m
			break
		fi
	done

	if test -z "$MYSQL_C_INC_DIR"
	then
		AC_MSG_ERROR([Didn't find the MySQL include dir in '$MYSQL_inc_check'])
	fi

	case "$MYSQL_C_INC_DIR" in
		/* ) ;;
		* )  AC_MSG_ERROR([The MySQL include directory ($MYSQL_C_INC_DIR) must be an absolute path.]) ;;
	esac


	AC_MSG_RESULT([$MYSQL_C_INC_DIR])

	CPPFLAGS="$CPPFLAGS -I${MYSQL_C_INC_DIR}"

    AC_MSG_CHECKING([if we can link to MySQL C API library directly])
	save_LIBS=$LIBS
	LIBS="$LIBS -l$MYSQL_C_LIB_NAME $MYSQLPP_EXTRA_LIBS"
	AC_TRY_LINK(
        [ #include <mysql.h> ],
        [ mysql_store_result(0); ],
        AC_MSG_RESULT([yes]),
        [ AC_MSG_RESULT([no])	
          LIBS="$save_LIBS"
          AC_CHECK_HEADERS(zlib.h, AC_CHECK_LIB(z, gzread, [],
              [ AC_MSG_ERROR([zlib not found]) ]))
          AC_MSG_CHECKING([whether adding -lz will let MySQL C API link succeed])
          MYSQLPP_EXTRA_LIBS="$MYSQLPP_EXTRA_LIBS -lz"
          LIBS="$save_LIBS -l$MYSQL_C_LIB_NAME $MYSQLPP_EXTRA_LIBS"
          AC_TRY_LINK(
              [ #include <mysql.h> ],

              [ mysql_store_result(0); ],
              AC_MSG_RESULT([yes]),
              [ AC_MSG_RESULT([no])
                AC_MSG_ERROR([Unable to link to MySQL client library!])
              ]

          )
        ])
	LIBS=$save_LIBS

	AC_SUBST(MYSQL_C_INC_DIR)
	AC_SUBST(MYSQL_C_LIB_DIR)
	AC_SUBST(MYSQL_C_LIB_NAME)
]) dnl MYSQL_C_API_LOCATION

Changes to test/manip.cpp.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
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
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85

86
87
88
89
90




91
92
93
94
95
96
97
98

99
100
101
102
103
104
105
106
107

108
109
110
111
112
113
114
115
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
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


/***********************************************************************
 test/manip.cpp - Tests the quoting and escaping manipulators.

 Copyright (c) 2007 by Educational Technology Resources, Inc.
 Others may also hold copyrights on code in this file.  See the
 CREDITS.txt file in the top directory of the distribution for details.

 This file is part of MySQL++.

 MySQL++ is free software; you can redistribute it and/or modify it
 under the terms of the GNU Lesser General Public License as published
 by the Free Software Foundation; either version 2.1 of the License, or
 (at your option) any later version.

 MySQL++ is distributed in the hope that it will be useful, but WITHOUT
 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
 License for more details.

 You should have received a copy of the GNU Lesser General Public
 License along with MySQL++; if not, write to the Free Software
 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
 USA
***********************************************************************/

#include <mysql++.h>

#include <iostream>
#include <sstream>
#include <string>


template <class T>
static bool
is_quoted(const std::string& s, T orig_str, size_t orig_len)
{
	return (s.length() == (orig_len + 2)) &&
			(s.at(0) == '\'') &&
			(s.at(orig_len + 1) == '\'') &&
			(s.compare(1, orig_len, orig_str) == 0);
}





template <class T>


static bool
is_quoted(const std::string& s, mysqlpp::Null<T> orig_str, size_t orig_len)
{
	return is_quoted(s, orig_str.data, orig_len);
}


// Stringish types should be quoted when inserted into Query when an
// explicit quote manipulator is used.
template <class T>
static bool
explicit_query_quote(T test, size_t len)
{
	mysqlpp::Query q(0);
	q << mysqlpp::quote << test;
	if (!is_quoted(q.str(), test, len)) {
		std::cerr << "Explicit quote of " << typeid(test).name() <<
				" in Query failed: " << q.str() << std::endl;
		return false;
	}

	mysqlpp::SQLStream s(0);
	s << mysqlpp::quote << test;
	if (is_quoted(s.str(), test, len)) {
		return true;
	}
	else {
		std::cerr << "Explicit quote of " << typeid(test).name() <<
				" in Query failed: " << q.str() << std::endl;
		return false;
	}
}


// Nothing should be quoted when inserted into an ostream, even when an
// explicit quote manipulator is used.  The manipulators are only for
// use with Query streams.
template <class T>
static bool
no_explicit_ostream_quote(T test, size_t len)
{

	std::ostringstream outs;
	outs << mysqlpp::quote << test;
	if (!is_quoted(outs.str(), test, len)) {
		return true;
	}




	else {
		std::cerr << "Explicit quote of " << typeid(test).name() <<
				" in ostream erroneously honored!" << std::endl;
		return false;
	}
}



// Nothing should be implicitly quoted as of v3.  We used to do it for
// mysqlpp::String (formerly ColData) when inserted into Query, but
// that's a silly edge case.  The only time end-user code should be
// using Strings to build queries via the Query stream interface is when
// using BLOBs or when turning result set data back around in a new
// query.  In each case, there's no reason for String to behave
// differently from std::string, which has always had to be explicitly
// quoted.
template <class T>

static bool
no_implicit_quote(T test, size_t len)
{
	std::ostringstream outs;
	outs << test;
	if (!is_quoted(outs.str(), test, len)) {
		mysqlpp::Query q(0);
		q << test;
		if (is_quoted(q.str(), test, len)) {
			std::cerr << typeid(test).name() << " erroneously implicitly "
					"quoted in Query: " << outs.str() <<
					std::endl;
			return false;

		}

		mysqlpp::SQLStream s(0);
		s << test;
		if (!is_quoted(s.str(), test, len)) {
			return true;
		}

		else {
			std::cerr << typeid(test).name() << " erroneously implicitly "
					"quoted in Query: " << outs.str() <<
					std::endl;
			return false;
		}

	}
	else {
		std::cerr << typeid(test).name() << " erroneously implicitly "
				"quoted in ostringstream: " << outs.str() <<
				std::endl;
		return false;
	}

}


// Run all tests above for the given type
template <class T>
static bool
test(T test, size_t len)
{
	return explicit_query_quote(test, len) &&
			no_explicit_ostream_quote(test, len) &&
			no_implicit_quote(test, len);
}


int
main()



{
	char s[] = "Doodle me, James, doodle me!";
	const size_t len = strlen(s);


	int failures = 0;
	failures += test(s, len) == false;
	failures += test(static_cast<char*>(s), len) == false;
	failures += test(static_cast<const char*>(s), len) == false;
	failures += test(std::string(s), len) == false;
	failures += test(mysqlpp::SQLTypeAdapter(s), len) == false;
	failures += test(mysqlpp::Null<std::string>(s), len) == false;
	return failures;

}



<
<
|
<
<
<
|
|
|
<
<
<
|

<
<
<
<
|
<
<
<
<
<
|
<
|
<
<
|

|
<
<
<
|
<
<
<
<
|
|
>
>
>

|
>
>
|
<
|
<
|
|
|
|
<
<
<
<
|
<
<
<
<
<
|
|
|
<
<
<
<
|
<
<
<
|
|
<
|
|
<
<
<
<
<
<
|
>
<
<
<
<
|
>
>
>
>
|
|
|
|
|
<
|
|
>
|
|
<
<
<
<
|
<
<
>
|
<
|
<
<
<
<
<
<
<
<
<
<
>
|
|
|
<
<
<
<
>
<
<
<
<
<
|
>
|
<
<
<
|
<
|
>
|
|
|
|
<
<
<
<
<
<
<
<
|
|
<
<
>
>
>
|
<
<
|
>
|
<
<
<
<
<
<
<
>
|
|
>
>


1



2
3
4



5
6




7





8

9


10
11
12



13




14
15
16
17
18
19
20
21
22
23

24

25
26
27
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


56
57

58










59
60
61
62




63





64
65
66



67

68
69
70
71
72
73








74
75


76
77
78
79


80
81
82







83
84
85
86
87


Platform Variations



~~~~~~~~~~~~~~~~~~~
    This file only covers details common to all Unix variants
    supported by MySQL++.  For platform-specific details, see the



    file appropriate to your OS:





        README-Cygwin.txt





        README-Linux.txt

        README-Mac-OS-X.txt


        README-Solaris.txt

    There are no special instructions for any other Unix flavors.









Building the Library and Example Programs
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    MySQL++ uses GNU autoconf, so you can build it with the standard
    commands:

    $ ./configure
    $ make
    $ su
    # make install




Configure Options
~~~~~~~~~~~~~~~~~
    The configure script takes several interesting options. Say:










        $ ./configure --help

    to get a list.  Some of the more interesting flags are:








    --prefix:


        If you wish to install mysql++ in a root directory other than
        /usr/local, run configure with --prefix=/some/dir/name







    --with-mysql*:





        If you installed MySQL in an atypical location, the configure
        script will not be able to find the library and header
        files without help.  The simplest way to clue configure into
        where MySQL is installed is with the --with-mysql option.
        Try something like "--with-mysql=/usr/local/mysql", for
        instance.  The configure script will then try to guess which
        subdirectories under the given directory contain the library
        and include files.


        If that doesn't work, it's because the library and header
        files aren't in typical locations under the directory you gave
        for configure to find them.  So, you need to specify them
        separately with --with-mysql-include and --with-mysql-lib
        instead.  As with --with-mysql, configure can often guess




        which subdirectory under the given directory contains the


        needed files, so you don't necessarily have to give the full
        path to these files.

    










    --with-field-limit:

        This lets you increase the maximum field limit for template
        queries and SSQLSes.  By default, both are limited to 25




        fields.  See chapter 8.2 in the user manual for details:






        http://tangentsoft.net/mysql++/doc/html/userman/configuration.html




    --enable-thread-check:


        Builds MySQL++ with threading support, if possible.
        
        This option simply turns on two tests: first, that your
        system uses a compatible threading library; and second,
        that the thread-safe version of the MySQL C API library








        (libmysqlclient_r) is installed and working.  If both of
        these are true, you get a thread-aware version of MySQL++.


        "Thread-aware" means that the library does make an effort to
        prevent problems, but we don't guarantee that all possible
        uses of MySQL++ are thread-safe.



        Note that this is a suggestion, not a command.  If we can't
        figure out the system's threading model or can't find the
        thread-aware build of the C API library, configure won't fail.







        It just reverts to the standard single-thread build.

        See the chapter on threading in the user manual for more
        details and advice on creating thread-safe programs with
        MySQL++.

Changes to test/null_comparison.cpp.

1
2


3
4
5




6
7
8

9




10
11










12
13









14




15
16
17
18
19

20
21


22




23
24

25




26




27

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





56



57






58
59



60
61








62





63
64
65

66
67







68
/***********************************************************************
 test/null_comparison.cpp - Tests that Null<T> and null_type comparison


	operators and SSQLS comparison functions work correctly.

 Copyright (c) 2008-2009 by Educational Technology Resources, Inc.




 Others may also hold copyrights on code in this file.  See the
 CREDITS.txt file in the top directory of the distribution for details.


 This file is part of MySQL++.





 MySQL++ is free software; you can redistribute it and/or modify it










 under the terms of the GNU Lesser General Public License as published
 by the Free Software Foundation; either version 2.1 of the License, or









 (at your option) any later version.





 MySQL++ is distributed in the hope that it will be useful, but WITHOUT
 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
 License for more details.


 You should have received a copy of the GNU Lesser General Public


 License along with MySQL++; if not, write to the Free Software




 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
 USA

***********************************************************************/









#include <mysql++.h>

#define MYSQLPP_ALLOW_SSQLS_V1	// suppress deprecation warning
#include <ssqls.h>




#include <iostream>

sql_create_1(ssqls, 1, 0, mysqlpp::Null<int>, a_column)









int
main()
{
	mysqlpp::Null<int> null_int = mysqlpp::null;
	mysqlpp::Null<int> non_null_int = 42;
	if (	!(null_int == non_null_int) &&
			(null_int != non_null_int) &&
			(null_int < non_null_int) &&
			!(non_null_int == null_int) &&
			(non_null_int != null_int) &&
			!(non_null_int < null_int) &&
			(null_int == mysqlpp::null) &&
			!(null_int != mysqlpp::null) &&







			(non_null_int != mysqlpp::null) &&






			!(non_null_int == mysqlpp::null) &&
			(mysqlpp::sql_cmp(null_int, null_int) == 0) &&





			(mysqlpp::sql_cmp(null_int, non_null_int) < 0) &&
			(mysqlpp::sql_cmp(non_null_int, null_int) > 0)) {
		ssqls foo(null_int), bar(non_null_int);
		if ((foo < bar) && (foo != bar) && !(bar < foo) && !(foo == bar)) {
			return 0;





		}



		else {






			std::cerr << "SSQLS comparison gave unexpected result" <<
					std::endl;



			return 1;
		}








	}





	else {
		std::cerr << "Null comparison gave unexpected result" << std::endl;
		return 1;

	}
}








<
<
>
>
|

|
>
>
>
>
|
|

>
|
>
>
>
>

|
>
>
>
>
>
>
>
>
>
>
|
|
>
>
>
>
>
>
>
>
>
|
>
>
>
>

<
<
<
|
>

|
>
>
|
>
>
>
>
|
|
>
|
>
>
>
>

>
>
>
>
|
>
|
<
>
>
>

<

<
>
>
>
>
>
>
>
>

|
|
|
|
|
|
|
|
|
|
|
|
|
>
>
>
>
>
>
>
|
>
>
>
>
>
>
|
|
>
>
>
>
>
|
|
|
<
<
>
>
>
>
>
|
>
>
>
|
>
>
>
>
>
>
|
|
>
>
>
|
|
>
>
>
>
>
>
>
>
|
>
>
>
>
>
|
|
<
>
|
|
>
>
>
>
>
>
>



1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
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
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74

75
76
77
78

79

80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
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
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


Visual C++ Version Compatibility
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    MySQL++ is fully functional with Visual C++ 2005 and 2008.

    MySQL++ also works with VC++ 2003 (a.k.a. VC++ 7.1), with the
    exception of the SSQLS feature.  There was partial support for
    SSQLS with VC++ 2003 in MySQL++ v2, but a feature we added in
    MySQL++ v3.0 crashes the VC++ 2003 compiler when you try to use
    even simple SSQLS, so we had to remove support for this entirely
    for that platform.  (See the v3.0 section in the Breakages chapter
    of the user manual for details.)

    Older versions of Visual C++ are basically hopeless when it
    comes to building current versions of MySQL++.  They have too
    many weaknesses in their Standard C++ implementation to build a
    modern library like MySQL++.  If you cannot upgrade your compiler,
    my advice is that you're best off programming straight to the
    MySQL C API rather than try to make MySQL++ build.


Where Are the Project Files, and Why So Many Versions?
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    There are three sets of .sln and .vcproj files shipped with
    MySQL++, in the vc2003, vc2005 and vc2008 subdirectories.
    Other than the SSQLS issue brought up above, there no functional
    difference between these versions.  We ship separate project
    files for each version of Visual Studio partly to save you from
    having to walk through the project conversion wizard, and partly
    so you can build the library with multiple versions of Visual C++
    without conflicts among the object files.


Prerequisites
~~~~~~~~~~~~~
    You need to have the Windows version of the MySQL server installed
    on your development system, even if you always access a MySQL
    server on a different machine.  This is because in addition to
    installing the server itself, the official MySQL Windows binaries
    also install the client-side development files that MySQL++
    needs in order to communicate with a MySQL server.  We call this
    the MySQL C API; MySQL++ is a C++ wrapper for this C API.

    You have to do a Custom install to enable installation of these
    development files.  If you get an error about mysql-version.h or
    mysql.h when building MySQL++, go back and reinstall the MySQL
    server, paying careful attention to the options.




    If you've installed the development files and are still getting
    build errors, read on.


Using Nonstandard MySQL Installations
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    The Visual Studio project files that come with MySQL++ have
    everything set up correctly for the common case.  The biggest
    assumption in the settings is that you're using MySQL 5.0
    (the newest version considered suitable for production use
    at the time of this writing) and that you installed it in
    the default location:

        C:\Program Files\MySQL\MySQL Server 5.0\

    If you installed a different version, or it's in a different
    directory, you need to change the project file settings to
    reference the C API development files in that other location.
    There are two ways to do this.

    The hard way is to make 4 different changes to 39 separate
    project files.  If you're a talented Visual Studio driver, you
    can do this in as little as about 5 or 6 steps.  You might even
    get it right the first time.

    The easy way is to install Bakefile (http://bakefile.org/),
    change the value of the MYSQL_WIN_DIR variable near the top of

    mysql++.bkl in the top level of the MySQL++ source tree, and run
    rebake.bat.  This will rebuild all of the project files for you,
    using the new MySQL path in all the many places it's needed.




Building MySQL++ for 64-Bit
~~~~~~~~~~~~~~~~~~~~~~~~~~~
    The MySQL++ Visual Studio project files ship with the assumption
    that you're building for 32-bit Windows.  While the utility
    of running the MySQL server on a 64-bit system is clear, that
    doesn't mandate running its client programs in 64-bit mode, too.
    As a result, we haven't yet bothered to come up with an easy way
    to change this.  Here's the hard way:

    - Follow the steps above to change the MySQL install location,
      if necessary.

    - Open the solution file, then say Build > Configuration Manager

    - Pull down the "Active solution platform" list box, say New...,
      and add "x64", copying settings from the Win32 build, and
      allowing it to create new project platforms.

    - Pull the same list box down, say Edit..., and remove the Win32
      build, unless you actually need both versions.

    It should then build.  If you get PRJ2009 errors, complaining
    about BuildLog.htm, this is a bug in Visual Studio 2008's
    new parallel build feature, which seems to affect x64 builds
    more than x86.  Sometimes you can get around it by just saying
    "build" repeatedly, each time getting a few more modules built.
    Or, you can disable the feature by going to Tools > Options... >
    Projects and Solutions > Build and Run > # of parallel processes
    and setting the value to 1.

    If you don't follow the instructions above carefully, you can
    end up with a completely unbuildable solution.  (It happened
    to me once when preparing these instructions!)  If you simply
    cannot seem to make it work, it's often simplest to just blow
    away the MySQL++ source tree, unpack a fresh copy and try again,
    paying more attention to the details.


Building the Library and Example Programs
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    You must build both the Debug and Release versions of the library,
    because a release build of your program won't work with a Debug
    version of the MySQL++ DLL.  These DLLs get different names, so
    you can install them in the same directory if needed: mysqlpp_d.dll
    for the Debug version, and mysqlpp.dll for the Release version.



    With the library built, run at least the resetdb and simple1
    examples to ensure that the library is working correctly.
    In addition to the other generic examples, there are a few
    Visual C++ specific examples that you might want to look at in
    examples\vstudio.  See README-examples.txt for further details.

    Once you're sure the library is working correctly, you can run
    the install.hta file at the project root to install the library
    files and headers in a directory of your choosing.
    
    (Aside: You may not have come across the .hta extension before.
    It's for a rarely-used feature of Microsoft's Internet Explorer,
    called HTML Applications.  Know what Adobe AIR is?  Kinda like
    that, only without the compilation into a single binary blob which
    you must install before you can run it.  Just open install.hta
    in a text editor to see how it works.)


Using MySQL++ in Your Own Projects
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    This is covered in the user manual, chapter 9.


Working With Bakefile
~~~~~~~~~~~~~~~~~~~~~
    MySQL++'s top-level Visual Studio project files aren't
    maintained directly.  Instead, we use a tool called Bakefile
    (http://bakefile.org/) to generate them from mysql++.bkl. Since
    there are so many project files in MySQL++, it's often simpler to
    edit this source file and "re-bake" the project files from it than
    to make your changes in Visual Studio.

    To do this, download the native Windows version of Bakefile from the
    web site given above.  Install it, and then put the installation
    directory in your Windows PATH.  Then, open up a command window, cd
    into the MySQL++ directory, and type "rebake".  This will run
    rebake.bat, which rebuilds the Visual Studio project files from
    mysql++.bkl.


    There's more information about using Bakefile in HACKERS.txt.


If You Run Into Problems...
~~~~~~~~~~~~~~~~~~~~~~~~~~~
    Especially if you have linking problems, make sure your project
    settings match the above.  Visual C++ is very picky about things
    like run time library settings.  When in doubt, try running one
    of the example programs.  If it works, the problem is likely in
    your project settings, not in MySQL++.

Changes to test/null_uniqueness.cpp.

1

2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

































































18


19

20






21

22


23
24
25
26
27
28




29
30


31

32
33


34
35




36
37
38
















39
/***********************************************************************

 test/null_uniqueness.cpp - Code for checking that null_type cannot be
	converted to anything else.  Because it triggers a compile-time
	check, it can't be included in the test suite.  You have to just
	try building it.  Comment out the assignment to int to check that
	the return statement also triggers the compile-time check.

 Copyright (c) 2008 by Educational Technology Resources, Inc.
 Others may also hold copyrights on code in this file.  See the
 CREDITS.txt file in the top directory of the distribution for details.

 This file is part of MySQL++.

 MySQL++ is free software; you can redistribute it and/or modify it
 under the terms of the GNU Lesser General Public License as published
 by the Free Software Foundation; either version 2.1 of the License, or
 (at your option) any later version.




































































 MySQL++ is distributed in the hope that it will be useful, but WITHOUT

 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or






 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public

 License for more details.



 You should have received a copy of the GNU Lesser General Public
 License along with MySQL++; if not, write to the Free Software
 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
 USA
***********************************************************************/





#include <mysql++.h>




int
main()


{
	mysqlpp::Null<int> ni = mysqlpp::null;




	int this_should_not_even_compile = mysqlpp::null;
	return ni;		// neither should this
}

















<
>
|
|
<
<
<
|
|
<
<
|
<
<
|
|
|
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

>
>
|
>
|
>
>
>
>
>
>
|
>
|
>
>
|
<
<
<
<
<
>
>
>
>
|
|
>
>

>
|
<
>
>
|
|
>
>
>
>
|
<
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>


1
2
3



4
5


6


7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
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
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93





94
95
96
97
98
99
100
101
102
103
104

105
106
107
108
109
110
111
112
113

114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131

#-######################################################################
# mysql++.m4 - Example autoconf macro showing how to find MySQL++
#	library and header files.



#
# Copyright (c) 2004-2009 by Educational Technology Resources, Inc.


#


# This file is free software; you can redistribute it and/or modify it
# under the terms of the GNU Lesser General Public License as published
# by the Free Software Foundation; either version 2.1 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
# Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public
# License along with MySQL++; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
# USA
#-######################################################################

dnl @synopsis MYSQLPP_DEVEL
dnl 
dnl This macro tries to find the MySQL++ library and header files.
dnl
dnl We define the following configure script flags:
dnl
dnl		--with-mysqlpp: Give prefix for both library and headers, and try
dnl			to guess subdirectory names for each.  (e.g. tack /lib and
dnl			/include onto given dir name, and other common schemes.)
dnl		--with-mysqlpp-lib: Similar to --with-mysqlpp, but for library only.
dnl		--with-mysqlpp-include: Similar to --with-mysqlpp, but for headers
dnl			only.
dnl
dnl This macro depends on having the default compiler and linker flags
dnl set up for building programs against the MySQL C API.  The mysql.m4
dnl macro in this directory fits this bill; run it first.
dnl
dnl @version 1.3, 2009/11/22
dnl @author Warren Young <mysqlpp@etr-usa.com>

AC_DEFUN([MYSQLPP_DEVEL],
[
	dnl
	dnl Set up configure script macros
	dnl
	AC_ARG_WITH(mysqlpp,
		[  --with-mysqlpp=<path>     path containing MySQL++ header and library subdirs],
		[MYSQLPP_lib_check="$with_mysqlpp/lib64 $with_mysqlpp/lib $with_mysqlpp/lib64/mysql++ $with_mysqlpp/lib/mysql++"
		  MYSQLPP_inc_check="$with_mysqlpp/include $with_mysqlpp/include/mysql++"],
		[MYSQLPP_lib_check="/usr/local/mysql++/lib64 /usr/local/mysql++/lib /usr/local/lib64/mysql++ /usr/local/lib/mysql++ /opt/mysql++/lib64 /opt/mysql++/lib /usr/lib64/mysql++ /usr/lib/mysql++ /usr/local/lib64 /usr/local/lib /usr/lib64 /usr/lib"
		  MYSQLPP_inc_check="/usr/local/mysql++/include /usr/local/include/mysql++ /opt/mysql++/include /usr/local/include/mysql++ /usr/local/include /usr/include/mysql++ /usr/include"])
	AC_ARG_WITH(mysqlpp-lib,
		[  --with-mysqlpp-lib=<path> directory path of MySQL++ library],
		[MYSQLPP_lib_check="$with_mysqlpp_lib $with_mysqlpp_lib/lib64 $with_mysqlpp_lib/lib $with_mysqlpp_lib/lib64/mysql $with_mysqlpp_lib/lib/mysql"])
	AC_ARG_WITH(mysqlpp-include,
		[  --with-mysqlpp-include=<path> directory path of MySQL++ headers],
		[MYSQLPP_inc_check="$with_mysqlpp_include $with_mysqlpp_include/include $with_mysqlpp_include/include/mysql"])

	dnl
	dnl Look for MySQL++ library
	dnl
	AC_CACHE_CHECK([for MySQL++ library location], [ac_cv_mysqlpp_lib],
	[
		for dir in $MYSQLPP_lib_check
		do
			if test -d "$dir" && \
				( test -f "$dir/libmysqlpp.so" ||
				  test -f "$dir/libmysqlpp.a" )
			then
				ac_cv_mysqlpp_lib=$dir
				break
			fi
		done

		if test -z "$ac_cv_mysqlpp_lib"
		then
			AC_MSG_ERROR([Didn't find the MySQL++ library dir in '$MYSQLPP_lib_check'])
		fi

		case "$ac_cv_mysqlpp_lib" in
			/* ) ;;
			* )  AC_MSG_ERROR([The MySQL++ library directory ($ac_cv_mysqlpp_lib) must be an absolute path.]) ;;
		esac
	])
	AC_SUBST([MYSQLPP_LIB_DIR],[$ac_cv_mysqlpp_lib])

	dnl
	dnl Look for MySQL++ header file directory
	dnl
	AC_CACHE_CHECK([for MySQL++ include path], [ac_cv_mysqlpp_inc],
	[





		for dir in $MYSQLPP_inc_check
		do
			if test -d "$dir" && test -f "$dir/mysql++.h"
			then
				ac_cv_mysqlpp_inc=$dir
				break
			fi
		done

		if test -z "$ac_cv_mysqlpp_inc"
		then

			AC_MSG_ERROR([Didn't find the MySQL++ header dir in '$MYSQLPP_inc_check'])
		fi

		case "$ac_cv_mysqlpp_inc" in
			/* ) ;;
			* )  AC_MSG_ERROR([The MySQL++ header directory ($ac_cv_mysqlpp_inc) must be an absolute path.]) ;;
		esac
	])
	AC_SUBST([MYSQLPP_INC_DIR],[$ac_cv_mysqlpp_inc])


	dnl
	dnl Now check that the above checks resulted in -I and -L flags that
	dnl let us build actual programs against MySQL++.
	dnl
	case "$ac_cv_mysqlpp_lib" in
	  /usr/lib) ;;
	  *) LDFLAGS="$LDFLAGS -L${ac_cv_mysqlpp_lib}" ;;
	esac
	CPPFLAGS="$CPPFLAGS -I${ac_cv_mysqlpp_inc} -I${MYSQL_C_INC_DIR}"
	AC_MSG_CHECKING([that we can build MySQL++ programs])
	AC_COMPILE_IFELSE(
		[AC_LANG_PROGRAM([#include <mysql++.h>],
			[mysqlpp::Connection c(false)])],
		AC_MSG_RESULT([yes]),
		AC_MSG_ERROR([no]))
]) dnl End MYSQLPP_DEVEL

Changes to test/qssqls.cpp.

1
2

3
4
5
6
7
8
9
/***********************************************************************
 test/qssqls.cpp - Tests SQL query creation from SSQLS in Query.


 Copyright (c) 2008-2009 by Educational Technology Resources, Inc.
 Others may also hold copyrights on code in this file.  See the
 CREDITS.txt file in the top directory of the distribution for details.

 This file is part of MySQL++.


|
>







1
2
3
4
5
6
7
8
9
10
/***********************************************************************
 test/null_comparison.cpp - Tests that Null<T> and null_type comparison
	operators and SSQLS comparison functions work correctly.

 Copyright (c) 2008-2009 by Educational Technology Resources, Inc.
 Others may also hold copyrights on code in this file.  See the
 CREDITS.txt file in the top directory of the distribution for details.

 This file is part of MySQL++.

25
26
27
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
56
57
58
59
60
61
62
63
64
65
66
67












68


69
70
71
72
73

74



75
76
77


#include <mysql++.h>
#define MYSQLPP_ALLOW_SSQLS_V1	// suppress deprecation warning
#include <ssqls.h>

#include <iostream>

using namespace mysqlpp;
using namespace std;


sql_create_19(test,
	19, 0,
	sql_tinyint,			tinyint_v,
	sql_tinyint_unsigned,	tinyint_unsigned_v,
	sql_smallint,			smallint_v,
	sql_smallint_unsigned,	smallint_unsigned_v,
	sql_int,				int_v,
	sql_int_unsigned,		int_unsigned_v,
	sql_mediumint,			mediumint_v,
	sql_mediumint_unsigned, mediumint_unsigned_v,
	sql_bigint,				bigint_v,
	sql_bigint_unsigned,	bigint_unsigned_v,
	sql_float,				float_v,
	sql_double,				double_v,
	sql_decimal,			decimal_v,
	sql_bool,				bool_v,
	sql_date,				date_v,
	sql_time,				time_v,
	sql_datetime,			datetime_v,
	sql_char,				char_v,	// only need one stringish type...
	sql_blob,				blob_v)	// ...and one blob type; they're all
									// the same under the hood in MySQL++

int
main()
{
	Query q(0);		// don't pass 0 for conn parameter in real code
	test empty(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, false,
			Date(), Time(), DateTime(), "", sql_blob());
	test filled(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11.0, 12.0, 13.0,
			bool(14), Date("1515-15-15"), Time("16:16:16"),
			DateTime("1717-17-17 17:17:17"), "18", sql_blob("1\09", 3));















	cout << q.insert(empty) << endl << endl;
	cout << q.insert(filled) << endl << endl;
	cout << q.replace(empty) << endl << endl;
	cout << q.replace(filled) << endl << endl;
	cout << q.update(filled, empty) << endl << endl;





	return 0;
}









<
<
<
<
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<




|
|
|
|
|
|
>
>
>
>
>
>
>
>
>
>
>
>
|
>
>
|
<
<
<
<
>
|
>
>
>
|
|
|
>
26
27
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
56
57
58
59




60
61
62
63
64
65
66
67
68

#include <mysql++.h>
#define MYSQLPP_ALLOW_SSQLS_V1	// suppress deprecation warning
#include <ssqls.h>

#include <iostream>





sql_create_1(ssqls, 1, 0, mysqlpp::Null<int>, a_column)






















int
main()
{
	mysqlpp::Null<int> null_int = mysqlpp::null;
	mysqlpp::Null<int> non_null_int = 42;
	if (	!(null_int == non_null_int) &&
			(null_int != non_null_int) &&
			(null_int < non_null_int) &&
			!(non_null_int == null_int) &&
			(non_null_int != null_int) &&
			!(non_null_int < null_int) &&
			(null_int == mysqlpp::null) &&
			!(null_int != mysqlpp::null) &&
			(non_null_int != mysqlpp::null) &&
			!(non_null_int == mysqlpp::null) &&
			(mysqlpp::sql_cmp(null_int, null_int) == 0) &&
			(mysqlpp::sql_cmp(null_int, non_null_int) < 0) &&
			(mysqlpp::sql_cmp(non_null_int, null_int) > 0)) {
		ssqls foo(null_int), bar(non_null_int);
		if ((foo < bar) && (foo != bar) && !(bar < foo) && !(foo == bar)) {
			return 0;
		}
		else {
			std::cerr << "SSQLS comparison gave unexpected result" <<
					std::endl;




			return 1;
		}
	}
	else {
		std::cerr << "Null comparison gave unexpected result" << std::endl;
		return 1;
	}
}

Changes to test/qstream.cpp.

1
2
3
4

5

6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27



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
56






57



58


59



60











61


62




63






64






65







66
67
68

69

70
71
72
73
74
75
76
77
78

79
/***********************************************************************
 test/qstream.cpp - Tests insertion of all officially-supported data
	types into a Query stream, plus some that aren't official.  Failure
	is defined as an exception being thrown for any one of these.



 Copyright (c) 2008 by Educational Technology Resources, Inc.
 Others may also hold copyrights on code in this file.  See the
 CREDITS.txt file in the top directory of the distribution for details.

 This file is part of MySQL++.

 MySQL++ is free software; you can redistribute it and/or modify it
 under the terms of the GNU Lesser General Public License as published
 by the Free Software Foundation; either version 2.1 of the License, or
 (at your option) any later version.

 MySQL++ is distributed in the hope that it will be useful, but WITHOUT
 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
 License for more details.

 You should have received a copy of the GNU Lesser General Public
 License along with MySQL++; if not, write to the Free Software
 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
 USA
***********************************************************************/




#include <mysql++.h>

#include <iostream>

using namespace mysqlpp;




















int
main()
{

















	try {






		// If you're reading this for implicit recommendations of good







		// code style, please ignore the hack-job on the following line.



		mysqlpp::Query q = mysqlpp::Connection().query();


		// Throw everything we can think of at Query's stream interface.
		// Don't do this in real code, either.
		q << 	sql_tinyint(0) << sql_tinyint_unsigned(0) <<
				sql_smallint(0) << sql_smallint_unsigned(0) <<
				sql_mediumint(0) << sql_mediumint_unsigned(0) <<
				sql_int(0) << sql_int_unsigned(0) << long(0) <<

				sql_bigint(0) << sql_bigint_unsigned(0) << longlong(0) <<
				sql_int1(0) << sql_int2(0) << sql_int3(0) <<
















				sql_int4(0) << sql_int8(0) << sql_middleint(0) <<




				sql_float(0) << sql_double(0) << sql_decimal(0) <<




				sql_numeric(0) <<
				sql_fixed(0) << sql_float4(0) << sql_float8(0) <<
				sql_bool(false) << sql_boolean(false) << bool(false) <<


				sql_enum() <<
				sql_char() << sql_varchar() << sql_long_varchar() <<






				sql_character_varying() << sql_long() <<



				sql_tinytext() << sql_text() <<


				sql_mediumtext() << sql_longtext() <<



				sql_blob() << sql_tinyblob() << sql_mediumblob() <<











				sql_longblob() << sql_long_varbinary() <<


				sql_date() << sql_time() << sql_datetime() <<




				sql_timestamp() <<






				sql_set();






		std::cout << q << std::endl;







		return 0;
	}
	catch (const mysqlpp::TypeLookupFailed& e) {

		std::cerr << "Query stream insert failed: " << e.what() <<

				std::endl;
		return 1;
	}
	catch (const std::exception& e) {
		std::cerr << "Unexpected exception: " << e.what() <<
				std::endl;
		return 1;
	}
}



|
|
|
>

>
|
|
|



















>
>
>




|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>


|

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

>
>
>
>
>
>
|
>
>
>
>
>
>
>
|
>
>
>
|
>
|
|
<
|
|
|
<
>
|
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
>
>
>
|
>
>
>
>
|
|
<
>
>
|
|
>
>
>
>
>
>
|
>
>
>
|
>
>
|
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
|
>
>
|
>
>
>
>
|
>
>
>
>
>
>
|
>
>
>
>
>
>
|
>
>
>
>
>
>
>
|

|
>
|
>
|


|
|
|


|
>
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
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
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100

101
102
103

104
105
106
107
108
109
110
111
112
113
114
115
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
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
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
/***********************************************************************
 resetdb.cpp - (Re)initializes the example database, mysql_cpp_data.
	You must run this at least once before running most of the other
	examples, and it is helpful sometimes to run it again, as some of
	the examples modify the table in this database.

 Copyright (c) 1998 by Kevin Atkinson, (c) 1999, 2000 and 2001 by
 MySQL AB, and (c) 2004-2008 by Educational Technology Resources, Inc.
 Others may also hold copyrights on code in this file.  See the CREDITS
 file in the top directory of the distribution for details.

 This file is part of MySQL++.

 MySQL++ is free software; you can redistribute it and/or modify it
 under the terms of the GNU Lesser General Public License as published
 by the Free Software Foundation; either version 2.1 of the License, or
 (at your option) any later version.

 MySQL++ is distributed in the hope that it will be useful, but WITHOUT
 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
 License for more details.

 You should have received a copy of the GNU Lesser General Public
 License along with MySQL++; if not, write to the Free Software
 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
 USA
***********************************************************************/

#include "cmdline.h"
#include "printdata.h"

#include <mysql++.h>

#include <iostream>

using namespace std;


// Pull in the sample database name from the cmdline module.
extern const char* kpcSampleDatabase;


// Convert a packed version number in the format used within MySQL++
// to a printable string.
static string
version_str(int packed)
{
	char buf[9];
	snprintf(buf, sizeof(buf), "%d.%d.%d",
			(packed & 0xFF0000) >> 16,
			(packed & 0x00FF00) >> 8,
			(packed & 0x0000FF));
	return buf;
}


int
main(int argc, char *argv[])
{
	// Ensure that we're not mixing library and header file versions.
	// This is really easy to do if you have MySQL++ on your system and
	// are trying to build a new version, and run the examples directly
	// instead of through exrun.
	if (mysqlpp::get_library_version() != MYSQLPP_HEADER_VERSION) {
		cerr << "Version mismatch: library is v" <<
				version_str(mysqlpp::get_library_version()) <<
				", headers are v" <<
				version_str(MYSQLPP_HEADER_VERSION) <<
				".  Are you running this" << endl <<
				"with exrun?  See README.examples." << endl;
		return 1;
	}
	
	// Connect to database server
	const char *server = 0, *user = 0, *pass = "";
	mysqlpp::Connection con;
	try {
		if (parse_command_line(argc, argv, 0, &server, &user, &pass)) {
			extern bool dtest_mode;
			if (dtest_mode) {
				cout << "Connecting to database server..." << endl;
			}
			else {
				cout << "Connecting to '" << 
						(user ? user : "USERNAME") << "'@'" <<
						(server ? server : "localhost") << "', with" <<
						(pass[0] ? "" : "out") << " password..." << endl;
			}
			con.connect(0, server, user, pass);
		}
		else {
			return 1;		// command line parsing failed
		}
	}
	catch (exception& er) {
		cerr << "Connection failed: " << er.what() << endl;
		return 1;
	}
	

	// Create new sample database, or re-create it.  We suppress
	// exceptions, because it's not an error if DB doesn't yet exist.
	bool new_db = false;

	{
		mysqlpp::NoExceptions ne(con);
		mysqlpp::Query query = con.query();
		if (con.select_db(kpcSampleDatabase)) {
			// Toss old tables, ignoring errors because it would just
			// mean the table doesn't exist, which doesn't matter.
			cout << "Dropping existing sample data tables..." << endl;
			query.exec("drop table stock");
			query.exec("drop table images");
			query.exec("drop table deadlock_test1");
			query.exec("drop table deadlock_test2");
		}
		else {
			// Database doesn't exist yet, so create and select it.
			if (con.create_db(kpcSampleDatabase) &&
					con.select_db(kpcSampleDatabase)) {
				new_db = true;
			}
			else {
				cerr << "Error creating DB: " << con.error() << endl;
				return 1;
			}
		}
	}

	// Create sample data table within sample database.
	try {
		// Send the query to create the stock table and execute it.
		cout << "Creating stock table..." << endl;
		mysqlpp::Query query = con.query();
		query << 

				"CREATE TABLE stock (" <<
				"  item CHAR(30) NOT NULL, " <<
				"  num BIGINT NOT NULL, " <<
				"  weight DOUBLE NOT NULL, " <<
				"  price DECIMAL(6,2) NOT NULL, " <<
				"  sdate DATE NOT NULL, " <<
				"  description MEDIUMTEXT NULL) " <<
				"ENGINE = InnoDB " <<
				"CHARACTER SET utf8 COLLATE utf8_general_ci";
		query.execute();

		// Set up the template query to insert the data.  The parse()
		// call tells the query object that this is a template and
		// not a literal query string.
		query << "insert into %6:table values " <<
				"(%0q, %1q, %2, %3, %4q, %5q:desc)";
		query.parse();

		// Set a default for template query parameters "table" and "desc".
		query.template_defaults["table"] = "stock";
		query.template_defaults["desc"] = mysqlpp::null;

		// Notice that we don't give a sixth parameter in these calls,
		// so the default value of "stock" is used.  Also notice that
		// the first row is a UTF-8 encoded Unicode string!  All you
		// have to do to store Unicode data in recent versions of MySQL
		// is use UTF-8 encoding.
		cout << "Populating stock table..." << flush;
		query.execute("Nürnberger Brats", 97, 1.5, 8.79, "2005-03-10");
		query.execute("Pickle Relish", 87, 1.5, 1.75, "1998-09-04");
		query.execute("Hot Mustard", 73, .95, .97, "1998-05-25",
				"good American yellow mustard, not that European stuff");
		query.execute("Hotdog Buns", 65, 1.1, 1.1, "1998-04-23");

		// Test that above did what we wanted.
		cout << "inserted " << con.count_rows("stock") << " rows." << endl;

		// Now create empty images table, for testing BLOB and auto-
		// increment column features.
		cout << "Creating empty images table..." << endl;
		query.reset();		// forget template query info
		query << 
				"CREATE TABLE images (" <<
				"  id INT UNSIGNED AUTO_INCREMENT, " <<
				"  data BLOB, " <<
				"  PRIMARY KEY (id)" <<
				")";
		query.execute();

		// Create the tables used by examples/deadlock.cpp
		cout << "Creating deadlock testing tables..." << endl;
		query.execute("CREATE TABLE deadlock_test1 (x INT) ENGINE=innodb");
		query.execute("CREATE TABLE deadlock_test2 (x INT) ENGINE=innodb");
		query.execute("INSERT INTO deadlock_test1 VALUES (1);");
		query.execute("INSERT INTO deadlock_test2 VALUES (2);");

		// Report success
		cout << (new_db ? "Created" : "Reinitialized") <<
				" sample database successfully." << endl;
	}
	catch (const mysqlpp::BadQuery& er) {
		// Handle any query errors
		cerr << endl << "Query error: " << er.what() << endl;
		return 1;
	}
	catch (const mysqlpp::BadConversion& er) {
		// Handle bad conversions
		cerr << endl << "Conversion error: " << er.what() << endl <<
				"\tretrieved data size: " << er.retrieved <<
				", actual size: " << er.actual_size << endl;
		return 1;
	}
	catch (const mysqlpp::Exception& er) {
		// Catch-all for any other MySQL++ exceptions
		cerr << endl << "Error: " << er.what() << endl;
		return 1;
	}

	return 0;
}

Changes to test/query_copy.cpp.



1
2
3




4



5


6

7

8







9




10







11







12



13


14










15


16






17





18







19



20

21

22

23

24




25
















































26







27





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




56


57




58



59

60


61




62



63

64















65



66

67





68



69


70





71


72

73




74


75

76















77


78







79

80


81



82





83



84
85





86




87

88

89



90



















91




92




93



94





95


96




97

98




99





100




101






102







103
104




105





/***********************************************************************
 test/query_copy.cpp - Tests SQL query copies, to ensure that we copy
 	it deeply enough.








 Copyright (c) 2009 by Educational Technology Resources, Inc.


 Others may also hold copyrights on code in this file.  See the

 CREDITS.txt file in the top directory of the distribution for details.









 This file is part of MySQL++.












 MySQL++ is free software; you can redistribute it and/or modify it







 under the terms of the GNU Lesser General Public License as published



 by the Free Software Foundation; either version 2.1 of the License, or


 (at your option) any later version.













 MySQL++ is distributed in the hope that it will be useful, but WITHOUT






 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or





 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public







 License for more details.





 You should have received a copy of the GNU Lesser General Public

 License along with MySQL++; if not, write to the Free Software

 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301

 USA




***********************************************************************/
























































#include <mysql++.h>












#include <iostream>









using namespace mysqlpp;





using namespace std;





static bool

test_parm(const char* testname, Query& q1, Query q2, const char* parm)

{


	string s1 = q1.str(parm);


	string s2 = q2.str(parm);



	if (s1.compare(s2) == 0) {





		return true;


	}



	else {



		std::cerr << "TEST " << testname << " failed: " <<




				"s1('" << s1 << "') != " <<



				"s2('" << s2 << "')!" << std::endl;


		return false;

	}



}






















static bool


test_plain(const char* testname, Query& q1, Query q2)



{
	if (q1.str().compare(q2.str()) == 0) {




		return true;


	}




	else {



		std::cerr << "TEST " << testname << " failed: " <<

				"q1('" << q1.str() << "') != " <<


				"q2('" << q2.str() << "')!" << std::endl;




		return false;



	}

}





















int





main()



{


	try {





		Query orig1(0);	// don't pass 0 for conn parameter in real code


		orig1 << "raw string insert method test";

		Query copy1(orig1);




		Query copy2(0); copy2 = orig1;




		Query orig2(0, false, "string ctor test"); // don't do this, either















		Query copy3(orig2);


		Query copy4(0); copy4 = orig2;









		Query orig3(0, false, "template %0 test");


		orig3.parse();



		Query copy5(orig3);





		Query copy6(0); copy6 = orig3;




		if (	test_plain("1a", orig1, copy1) &&





				test_plain("1b", orig1, copy2) &&




				test_plain("2a", orig2, copy3) &&

				test_plain("2b", orig2, copy4) &&

				test_parm("3a", orig3, copy5, "query") &&



				test_parm("3b", orig3, copy6, "query")) {



















			return 0;




		}




	}



	catch (const mysqlpp::Exception& e) {





		std::cerr << "Query copy test failed: " << e.what() <<


				std::endl;




	}

	catch (const std::exception& e) {




		std::cerr << "Unexpected exception: " << e.what() <<





				std::endl;




	}














	return 1;
}








>
>
|
<
|
>
>
>
>

>
>
>
|
>
>
|
>
|
>

>
>
>
>
>
>
>
|
>
>
>
>

>
>
>
>
>
>
>
|
>
>
>
>
>
>
>
|
>
>
>
|
>
>
|
>
>
>
>
>
>
>
>
>
>

>
>
|
>
>
>
>
>
>
|
>
>
>
>
>
|
>
>
>
>
>
>
>
|
>
>
>

>
|
>
|
>
|
>
|
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

>
>
>
>
>
>
>
|
>
>
>
>
>

>
>
>
>
>
>
|
>
>
>
>
>
>

>
>
|
>
>
>
>
>
|
>

>

>
|
>
|
>
|
>
>
|
>
>
|
>
>
>
|
>
>
>
>
>
|
>
>
|
>
>
>
|
>
>
>
|
>
>
>
>
|
>
>
>
|
>
>
|
>
|
>
>
>
|
>
>

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

>
>
>
>
|
>
>
|
>
>
>
|
|
>
>
>
>
|
>
>
|
>
>
>
>
|
>
>
>
|
>
|
>
>
|
>
>
>
>
|
>
>
>
|
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

>
>
>

>
|
>
>
>
>
>
|
>
>
>
|
>
>
|
>
>
>
>
>
|
>
>
|
>
|
>
>
>
>
|
>
>
|
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
>
|
>
>
>
>
>
>
>

>
|
>
>
|
>
>
>
|
>
>
>
>
>
|
>
>
>
|
|
>
>
>
>
>
|
>
>
>
>
|
>
|
>
|
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
>
>
>
|
>
>
>
>
|
>
>
>
|
>
>
>
>
>
|
>
>
|
>
>
>
>
|
>
|
>
>
>
>
|
>
>
>
>
>
|
>
>
>
>
|
>
>
>
>
>
>

>
>
>
>
>
>
>
|
|
>
>
>
>

>
>
>
1
2
3

4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
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
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
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
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
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
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
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
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
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
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
Patches for any of these thoughtfully considered!  See the HACKERS.txt
file for instructions on sending patches.


Any Version
-----------
    o The DateTime family's time_t conversion operators should detect
      DATETIME("0") type values and return time_t(0) rather than
      attempt to stuff an out-of-range value into a smaller box.

    o Any time you must hand-roll some SQL code in your program,
      consider whether it could be generalized to a widely-useful
      API feature.

    o Suppress DOS line-ending related diffs from examples/cgi_jpeg
      output when running dtest on Windows.  Check for -D?

    o Need to link statically to connect to MySQL Embedded?

      http://stackoverflow.com/questions/672451/

    o When Bakefile allows, bring examples/vstudio/* into the top-level
      build system.  This will let us generate separate project
      files for each VC++ version we support, let us use MYSQL_WIN_DIR
      variable instead of hard-coded paths, and build against the local
      version of MySQL++ instead of requiring it to be installed first.
      Should probably drop the MFC example project, to avoid requiring
      Visual C++ Professional.

    o Query::storein(slist<T>&) is unusable.  As a template method, it
      must be defined in a header file; we cannot #include config.h from
      a header, thus the proper HAVE macro that would let us define this
      template method is never defined.

      One solution is to create lib/slist.h.in, parameterized by the
      detected slist type name and the header file defining it.  This
      will #include the proper header file, define SList<T>::Type (a
      template typdedef: http://www.gotw.ca/gotw/079.htm), and #define
      MYSQLPP_HAVE_SLIST.  Then Query::storein() can be wrapped by an
      ifdef checking for MYSQLPP_HAVE_SLIST, only defined when the
      configure script found a suitable slist type.

      Also create a default lib/slist.h file, checked into svn as
      lib/slistdef.h and copied to slist.h on tarball creation.  Remove
      this file early in configure script run, so we're forced to
      overwrite its contents with detected values.  Default version
      contains ifdefs for non-autoconf platforms where we know what
      slist definition is available on that platform.  Xcode, for
      instance, will let us use <ext/slist>.

    o Add ctor and assignment operator that takes mysqlpp::null.  You
      now have to call a 4-argument version of either the ctor or
      assign() to get a NULL SQL string.

    o The escape_q() functions aren't returning the right value when
      dealing with Null<T> wrapped types, such as sql_blob_null.

    o The current method SSQLS uses to compare floating point numbers
      is highly dubious.  It just subtracts them, and checks that
      the absolute difference is under some threshold.  The manual
      warns that this is fine for "human scale" applications, but even
      that's not actually true.  It means that if Larry Ellison loses
      a hundredth of a penny in his couch, it is somehow significant.
      I have no idea how much money Larry Ellison is comfortable losing
      to his couch cushions, but it's probably closer to 1 ppm than
      the current threshold, which is 100 parts per quadrillion on
      the scale of $1 bn.

      For backards compatibility, we should keep this method, but we
      should add these two more mathematically sound methods:

      - Percentage: Divide the smaller number into the larger, then
        compare against a threshold.  The default should be
        something like 1.000001 (1 ppm), which lets us make much
        finer distinctions without running out of precision, even
        with single-precision numbers counting Bill Gates' losses to
        his couch cushions.

      - Logarithmic, or "Bels": Same as percentage, but on a log10
        scale so it works better for FP numbers, which are based on
        powers of 10.  Logarithms are more costly than division,
        and we still need a division for this, so it shouldn't be
        the new default.

        1 ppm is ~4.3e-7, which is below what single-precision FP
        can distinguish.  Increasing the threshold to a value you
        *can* distinghish with a 32-bit IEEE float makes it ignore
        significant amounts of money in Carlos Slim's couch cusions.
        (Hundreds of dollars.)  Therefore, we should use something
        like 1e-7 or 1e-8 anyway, and make it clear that the default
        threshold is only suitable for doubles.
        
        Someone using single precision FP should increase the threshold
        to 1e-5 or so.  Such a person would be assumed to know what
        they're doing.

        It's probably more efficient to change the algorithm from:

           double diff = log10(a > b ? a / b : b / a);

        to:

          double diff = fabs(log10(a / b));

        Logarithms give the same magnitude result for a/b as b/a,
        differing only in sign.  fabs() is probably implemented as
        an intrinsic that just clears a single bit, which should be
        cheaper than a floating point comparison followed by a jump.

        With suitable tuning, this method would allow you to
        distinguish the change lost by a single Pentagon contractor's
        lobbyist to a single couch, on a single occasion, as compared
        to the combined net worth of all Pentagon contractors and
        their employees, assigns, mistresses, and, ah, hired help.
        If you use doubles, anyway.


v3.3 Plan: Finish SSQLS v2
--------------------------
    See http://lists.mysql.com/plusplus/6929 for high-level plan.

    o Goal: Restore VC++ 2003 compatibility with SSQLS, lost with v1

    o C++ code generator, from walking DSL parse tree:

      examples/stock.ssqls gives ssqls_stock.h containing:

          class SQLStock : public mysqlpp::SsqlsBase
          {
          public:
              SQLStock(Connection* conn = 0); // default ctor
              SQLStock(const SQLStock& other);
              SQLStock(const mysqlpp::Row& row,
                      Connection* conn = 0); // full init from query
              SQLStock(mysqlpp::sql_bigint key1); // exemplar creation
              SQLStock(Connection* conn,
                      mysqlpp::sql_bigint key1) // calls load();
              SQLStock(
                  mysqlpp::sql_bigint f1,
                  mysqlpp::sql_bigint f2,
                  mysqlpp::sql_double f3,
                  mysqlpp::sql_double f4,
                  const mysqlpp::sql_date& f5,
                  const mysqlpp::sql_mediumtext& f6); // full init
              SQLStock(Connection* conn,
                  mysqlpp::sql_bigint f2,
                  mysqlpp::sql_double f3,
                  mysqlpp::sql_double f4,
                  const mysqlpp::sql_date& f5,
                  const mysqlpp::sql_mediumtext& f6); // calls create()
              SQLStock(Connection* conn,
                  mysqlpp::sql_bigint f1,
                  mysqlpp::sql_bigint f2,
                  mysqlpp::sql_double f3,
                  mysqlpp::sql_double f4,
                  const mysqlpp::sql_date& f5,
                  const mysqlpp::sql_mediumtext& f6); // calls save()

              bool createTable(Connection* conn = 0) const;
              const char* getTableName() const
                      { return class_table_name_ || table(); }
              void setTableName(const char* name)
                      { instance_table(name); }
              static void setTableName(const char* name)
                      { class_table_name_ = name; }

              std::ostream& equal_list(std::ostream& os) const;
              std::ostream& json(std::ostream& os) const;
              std::ostream& name_list(std::ostream& os) const;
              std::ostream& value_list(std::ostream& os) const;
              std::ostream& xml(std::ostream& os) const;

              mysqlpp::sql_bigint getId() const;
              mysqlpp::sql_bigint getNum() const;
              mysqlpp::sql_double getWeight() const;
              mysqlpp::sql_double getPrice() const;
              const mysqlpp::sql_date& getSdate() const;
              const mysqlpp::sql_mediumtext& getDescription() const;

              void setId(mysqlpp::sql_bigint value);
              void setNum(mysqlpp::sql_bigint value);
              void setWeight(mysqlpp::sql_double value);
              void setPrice(mysqlpp::sql_double value);
              void setSdate(const mysqlpp::sql_date& value);
              void setDescripion(const mysqlpp::sql_mediumtext& value);

              bool operator<(const SQLStock& rhs) const;
              SQLStock& operator=(const SQLStock& rhs);

          protected:
              mysqlpp::sql_bigint id_;
              mysqlpp::sql_bigint num_;
              mysqlpp::sql_double weight_;
              mysqlpp::sql_double price_;
              mysqlpp::sql_date sdate_;
              mysqlpp::sql_mediumtext description_;

              std::bitset<6> set_fields_;

          private:
              static const char* class_table_name_;
          };

      ...and ssqls_stock.cc, containing implementation for same.

    o Ensure we're using case-insensitive SQL column to C++ field name
      matching.  Column names aren't case-sensitive in SQL.

    o SQL table updater/builder, -T option, taking .ssqls and
      creating or updating the DB table to match.

    o If using accessors, generate "std::bitset<num_fields> is_set_",
      and set the appropriate bit when calling each setFoo() so we
      can intuit which fields were set.  Probably also need an enum:

          enum FieldIndices {
              id_field_index_,
              num_field_index_,
              ...
          };

      This will allow Query::select(), for instance, to figure out that
      we want it to select by a non-key field, returning all matches.

    o Define operator<< for SSQLS and a set of manipulators which
      govern whether the operator calls equal_list(), json(),
      name_list(), value_list(), or xml() to do the actual insertion.

    o Define operator<< for sequence_container<SsqlsBase> and similar
      for associative containers.  Give mysql(1)-like ASCII grid or
      some other table format.

    o Define operator>> for SSQLS, taking XML as input, in the form
      emitted via xml().  expat uses the new BSD license, so maybe
      we can just drop it in the tree, with an option to use the
      platform expat on autoconf systems.

    o MySQL table metadata to SSQLSv2 data structure translator.
      (-s, -u, -p and -t flag support.)  Add this to dtest, extracting
      stock.ssqls definition from DB.

    o Replace Query's template methods taking SSQLSes with concrete
      methods taking const SsqlsBase&.

    o Create Query::remove(const SsqlsBase&)

    o Try to remove of 'explicit' from Date, DateTime and Time
      ctors taking stringish types.  (Can't do it for real until v4,
      but we can lay the ground work here.)

    o Auto-create() ctor: if there is an auto_increment field,
      populate it on query success.

    o Detect ctor conflicts corresponding to sql_create_N(N, N...)
      in SSQLSv1.  ssqlsxlat can be smart enough to just not emit
      duplicate ctors.

    o Special case of ctor suppression: if the number of key fields
      equals the total number of fields, you get an auto-load() ctor,
      not auto-update().

    o Replace CREATE TABLE SQL in resetdb with create_table() calls.

    o Option to use integer indices into Row when populating?  Only
      bother if it gives a speed advantage we can actually see,
      because it removes all the dynamic typing advantages we got
      with the change to field name indices in v3.0.

    o Try to add Query::storein(container, ssqls), which generates
      SELECT * from {ssqls.table()} and stores the result.  May not be
      possible due to existing overloads, but try.  If it works, use
      this form in the userman Overview section, saving one LOC.

    o Convert SSQLS v1 examples to v2.  SSQLS v2 isn't done until
      there's a straightformward conversion path for all examples.

    o Add #warning to generated ssqls.h saying that you should now use
      SSQLS v2.  Wrap it in a check for MYSQLPP_ALLOW_SSQLS_V1,
      so people can disable the warning.


v3.4 Tentative Plan
-------------------
    o Add Query::storein<Container, T>(container), getting table
      name from container::value_type.table() instead.

    o Define operator<< for Fields, Row, StoreQueryResult, etc., giving
      CSV format.

    o Remove libexcommon.  Between above and SSQLSv2, we should have
      everything we need to get equivalent output without special
      purpose code.  There should be no ad hoc data dumping code in
      the examples.

    o Bring back mandatory quoting for manipulators?  If someone says
      os << mysqlpp::escape << foo; do they not really really mean
      escape foo?  Automatic quoting and escaping is different.  See

      http://lists.mysql.com/plusplus/7999

    o Configure script should try to get MySQL C API directories
      from mysql_config.

    o If pkg-config is available, register ourselves with it using
      information discovered by configure.  Also, write out a
      mysql++-config script, which either wraps pkg-config or
      reinvents it, poorly, for systems that don't have it.

    o Add String::operator==(const mysqlpp::null_type&).  Needed to
      allow comparison of row[x] returns to SQL null.  Change one of
      the examples to show it?

    o Memory "leak" and C API library init fixes:
    
      - Add DBDriver::library_begin() and library_end(), wrapping
        similarly named functions in the C API.

      - Create Process class, which you create at the top of main()
        on the stack, purely to call these automatically.

      - Update userman to recommend creating Process object in
        ConnectionPool derivatives, instead.

      - Create Thread class to call existing DBDriver::thread_start()
        and thread_end(), similar to Process, created on the stack
        of the thread entry function.

      - Move memory leak FAQ into userman, rewriting it to cover
        all this.

    o mysqlpp::execute manipulator.  Immediately executes built
      query string.  Works best with exceptions, as that's the only way
      to detect failures.

    o Chris Frey's packarray class

    o Create adaptors for std::bitset, for storing binary data in a
      MySQL table.  Make two options available, one for storing the
      return from bitset::to_ulong() in an UNSIGNED INTEGER column,
      and another for storing a larger set of bits in a more flexible
      way, perhaps as a BLOB.

    o Create a backtick manipulator for use by field_list() in row.h
      and ssqls.h.  These currently use do_nothing0, but that prevents
      use of SQL reserved words as identifiers.

    o Has experience with new thread awareness changed our mind on
      atomic inc/dec of reference counts in RefCounted*?

    o Create a fixed-point data type for use with SQL's DECIMAL and
      related types.  Right now, sql_decimal is a typedef for double,
      so you lose accuracy in the fractional part.  Don't forget to
      include an "is_null" flag to cope with conversion from infinite
      or NaN float values; that's how MySQL stores these.

    o Optional checked conversions in String for numerics: throw
      BadConversion on range overflow?

    o Add Query::storein_if(), mirroring store_if()

    o Add a method to mysqlpp::String to return a widened version of the
      string.  Probably make return type templatized so we can return
      wstring, C++/CLI native strings, etc.  Then convert examples that
      do this conversion to use this new mechanism.

    o Try to add operator std::string to String.  If it doesn't work,
      explain why not in the userman, and in Row::operator[] refman.
      
    o Wrap LOAD DATA INFILE:

      bool Query::load_file(
          const char* path,
          bool local_path,
          const char* table,
          const char* field_terminator = 0,   // default \t
          const char* field_encloser = 0,     // default none
          const char* field_escape = 0,       // default \
          const char* line_terminator = 0,    // \n on *ix, \r\n on Windows
          const char* line_starter = 0,       // default none
          const char* character_set = 0,      // default UTF-8
          const char* comment_prefix = 0,     // ignore no lines
          bool replace_existing = false,
          bool ignore_duplicates = false,
          bool low_priority = false,
          int skip_lines = 0);

    o Wrappers for above: load_local_tab_file(), load_local_csv_file(),
      load_remote_*()...

    o Query::save_file() interfaces, wrapping SELECT ... INTO FILE,
      modeled on above.


v4.0 or Later
-------------
    o Database independence:

      - Use libdbi or similar?  http://libdbi.sf.net/

      - Make DBDriver class purely abstract; move its entire functional
        contents to new MysqlDriver.

      - Must create at least two other DBDriver subclasses to
        ensure base class is reusable before releasing v4.0.
        PostgresDriver and SqlLiteDriver?

      - Templatize all classes that use DBDriver interface with the
        DB driver type.  This lets you specify the driver type to use
        with a Connection and all its children without modifying the
        existing method parameter lists.  This also lets us worry less
        about C API types, as they can be hidden away behind typedefs:

        class MysqlDriver : public DBDriver { ...
           typedef MYSQL_ROW row_type;
           ...
        }

        template <class DBD = MysqlDriver>
        class Connection ... { ...
           Query<DBD> query();
           ...
        }

        template <class DBD = MysqlDriver>
        class UseQueryResult { ...
            DBD::row_type fetch_raw_row();
        }

      - Tricky bits:
    
        - Initializing result set objects.

        - type_info module.  Extremely closely tied to MySQL C API
          right now.  Will probably have to turn it into a parallel
          class hierarchy to DBDriver, or fold it in with same.

        - Building MySQL++ on systems without autoconf.  How to
          specify what DB engines are available?  Probably default to
          supporting MySQL only, and let people turn things on manually
          as they need them.  Or, maybe make them use Bakefile so they
          can fiddle with the options if they want something atypical.

    o Fork mysqlpp::String into mysqlpp::Blob, which differs only in
      that it knows that it should be automatically quoted and escaped
      when inserted into a SQL query.  Could do this in 3.x, but it's a
      pretty serious API breakage.

    o Some sort of support for prepared statements.  Can we hijack
      the template query mechanism?

    o If SSQLSv2 does use a common base class, change Query template
      methods taking SSQLS into concrete methods taking SsqlsBase&.

    o Make Query::insert(), replace() and update() execute their
      queries immediately.  Requires an ABI break, because they'll
      have to return SimpleResult.

    o Switch Query's safe bool to overload basic_ios<>::operator
      void*() instead.  We create an ambiguous conversion in bool
      context with some C++ standard libraries otherwise.

    o Templatize mysqlpp::String on value_type so it can be used to
      hold wide characters.  Then the method that converts UTF-8 to the
      platform's best wide character type can just return a different
      variant of mysqlpp::String.

    o Add wrapper functions to Null<> like length() that call the
      corresponding function on data member, if present, to make it
      more transparent.  At minimum, mirror the std::string API.

    o Transaction class should check an "in transaction" flag on
      Connection (or DBDriver) before sending BEGIN, defaulting to
      false.  If set, the Transaction object does nothing.  If not
      set, set it and send the query.  This prevents it from trying
      to set up nested queries, which MySQL doesn't support.

    o Remove throw-spec for std::out_of_range from SQLTypeAdapter::at().
      It no longer throws this, and throw-specs are passee' anyway.

    o Store failed query string in BadQuery exception object, to make
      logging and debugging easier.  One could have a try block wrapping
      many queries, and be able to recover the failed query string from
      the exception object, instead of somehow keeping track yourself.

      Patch: http://lists.mysql.com/plusplus/8374
 
    o Query and SQLStream could have a common base class that would
      allow the stream manipulator functions to catch and modify
      strings based on only one dynamic_cast instead of requiring
      two as it does since the addition of the SQLStream class.

    o Make internal call chain steps like Query::execute(SQLQueryParms&)
      protected?  No good reason for end users to call it, and making
      it part of the public API causes people to try calling it, and
      discovering that it's not a very elegant interface, compared to
      the ones taking SQLStrings.

    o SQL time type allows +/- 839 hours of range.  v3.0 code doesn't
      cope with negative times, and if we change it to use signed
      integers, we'll still only get +/-127 hours instead of +255.
      Need to switch the hour field to a short to get the full range.

    o Create a thread-safe message queue for separating DB access and
      data use into multiple threads.  Something like ConnectionPool,
      optional and with no ties to the internals of MySQL++.  There
      could be an adapter between one end of the queue and a Connection
      object, which creates Queries to handle standardized messages,
      delivering the results back to the queue.

    o Get rid of two-step create in DBDriver, requiring a connection to
      be established in ctor for object to be valid?  RAII.  The
      DB-specific functions that don't require a connection can be
      static methods.  Tricky bit: a failed Connection::connect() call
      will likely be followed by an indirect call to DBDriver::err*().
      Does Connection cache the error value and message?  If we can pull
      this off, we can drop the DBDriver::is_connected_ flag and change
      Connection::connected() to "return driver_ != 0".

    o Add STL-like custom Allocator template parameters to memory-hungry
      classes like Row?  Useful in apps that process lots of data over
      long periods, causing heap fragmentation with the default C++
      allocator.

    o Audit library for non-virtual methods that could be profitably
      made virtual.  Many are non-overridable now purely because
      changing them would break the ABI, so now's the time to fix that.

Changes to test/sqlstream.cpp.

1
2
3


4

5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27

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
56
57
58
59
60
61
62

63
64
65
66
67









68



69





70



















71


72
73
74






75
















76



77












78






79



80











81


82











83






84






85

86









87


88
89
90
91
/***********************************************************************
 test/sqlstream.cpp - Tests SQLStream class, which is handled by the 
 stream manipulators just like Query.




 Copyright (c) 2008 by AboveNet, Inc.  Others may also hold copyrights 
 on code in this file.  See the CREDITS file in the top directory of 
 the distribution for details.

 This file is part of MySQL++.

 MySQL++ is free software; you can redistribute it and/or modify it
 under the terms of the GNU Lesser General Public License as published
 by the Free Software Foundation; either version 2.1 of the License, or
 (at your option) any later version.

 MySQL++ is distributed in the hope that it will be useful, but WITHOUT
 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
 License for more details.

 You should have received a copy of the GNU Lesser General Public
 License along with MySQL++; if not, write to the Free Software
 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
 USA
***********************************************************************/

#include <mysql++.h>

#define MYSQLPP_ALLOW_SSQLS_V1	// suppress deprecation warning
#include <ssqls.h>
#include <sqlstream.h>

#include <iostream>


using namespace mysqlpp;
using namespace std;


sql_create_23(test,
	23, 0,
	sql_tinyint,			tinyint_v,
	sql_tinyint_unsigned,	tinyint_unsigned_v,
	sql_smallint,			smallint_v,
	sql_smallint_unsigned,	smallint_unsigned_v,
	sql_int,				int_v,
	sql_int_unsigned,		int_unsigned_v,
	sql_mediumint,			mediumint_v,

	sql_mediumint_unsigned, mediumint_unsigned_v,
	sql_bigint,				bigint_v,
	sql_bigint_unsigned,	bigint_unsigned_v,
	sql_float,				float_v,
	sql_double,				double_v,
	sql_decimal,			decimal_v,
	sql_bool,				bool_v,
	sql_date,				date_v,
	sql_time,				time_v,
	sql_datetime,			datetime_v,
	sql_char,				char_v,
	sql_varchar,			varchar_v,
	sql_tinytext,			tinytext_v,
	sql_text,				text_v,
	sql_mediumtext,			mediumtext_v,
	sql_longtext,			longtext_v)



int
main()
{









	SQLStream sqls(0);		// don't do this in real code



	test empty(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, false,





			Date(), Time(), DateTime(),"","","","","","");



















	test filled(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11.0, 12.0, 13.0,


			bool(14), Date("1515-15-15"), Time("16:16:16"),
			DateTime("1717-17-17 17:17:17"),"18","19","20","21","22","23");







	sqls << "INSERT INTO " << filled.table() << " (" <<
















			filled.field_list() << ") VALUES (" <<



			filled.value_list() << ")";



















	cout << sqls.str() << endl;















	sqls.str("");














	sqls << "INSERT INTO " << empty.table() << " (" <<






			empty.field_list() << ") VALUES (" <<






			empty.value_list() << ")";











	cout << sqls.str() << endl;



	return 0;
}


|
|
>
>

>
|
|
|



















|
>
|
|
<


>

<



|
|
|
|
|
|
|
|
<
>
|
|
|
|
|
<
<
<
<
|
<
<
<
<
<
<
>



|

>
>
>
>
>
>
>
>
>
|
>
>
>
|
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
>
|
<
|
>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>

>
>
>
>
>
>
|
>
>
>

>
>
>
>
>
>
>
>
>
>
>
|
>
>

>
>
>
>
>
>
>
>
>
>
>
|
>
>
>
>
>
>
|
>
>
>
>
>
>
|
>
|
>
>
>
>
>
>
>
>
>
|
>
>



<
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
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






56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104

105
106
107
108
109
110
111
112
113
114
115
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
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
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

/***********************************************************************
 resetdb.cpp - (Re)initializes the example database, mysql_cpp_data.
	You must run this at least once before running most of the other
	examples, and it is helpful sometimes to run it again, as some of
	the examples modify the table in this database.

 Copyright (c) 1998 by Kevin Atkinson, (c) 1999-2001 by MySQL AB, and
 (c) 2004-2009 by Educational Technology Resources, Inc.  Others may
 also hold copyrights on code in this file.  See the CREDITS file in
 the top directory of the distribution for details.

 This file is part of MySQL++.

 MySQL++ is free software; you can redistribute it and/or modify it
 under the terms of the GNU Lesser General Public License as published
 by the Free Software Foundation; either version 2.1 of the License, or
 (at your option) any later version.

 MySQL++ is distributed in the hope that it will be useful, but WITHOUT
 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
 License for more details.

 You should have received a copy of the GNU Lesser General Public
 License along with MySQL++; if not, write to the Free Software
 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
 USA
***********************************************************************/

#include "cmdline.h"
#include "printdata.h"

#include <mysql++.h>


#include <iostream>
#include <cstdio>


using namespace std;


// Pull in the sample database name from the cmdline module.
extern const char* kpcSampleDatabase;


// Convert a packed version number in the format used within MySQL++
// to a printable string.
static string
version_str(int packed)

{
	char buf[9];
	snprintf(buf, sizeof(buf), "%d.%d.%d",
			(packed & 0xFF0000) >> 16,
			(packed & 0x00FF00) >> 8,
			(packed & 0x0000FF));




	return buf;






}


int
main(int argc, char *argv[])
{
	// Ensure that we're not mixing library and header file versions.
	// This is really easy to do if you have MySQL++ on your system and
	// are trying to build a new version, and run the examples directly
	// instead of through exrun.
	if (mysqlpp::get_library_version() != MYSQLPP_HEADER_VERSION) {
		cerr << "Version mismatch: library is v" <<
				version_str(mysqlpp::get_library_version()) <<
				", headers are v" <<
				version_str(MYSQLPP_HEADER_VERSION) <<
				".  Are you running this" << endl <<
				"with exrun?  See README.examples." << endl;
		return 1;
	}
	
	// Get connection parameters from command line
	mysqlpp::examples::CommandLine cmdline(argc, argv);
	if (!cmdline) {
		return 1;
	}

	// Connect to database server
	mysqlpp::Connection con;
	try {
		if (cmdline.dtest_mode()) {
			cout << "Connecting to database server..." << endl;
		}
		else {
			const char* u = cmdline.user() ? cmdline.user() : "";
			const char* s = cmdline.server() ? cmdline.server() : "localhost";
			cout << "Connecting to '" << u << "'@'" << s << "', with" <<
					(cmdline.pass() && cmdline.pass()[0] ? "" : "out") <<
					" password..." << endl;
		}
		con.connect(0, cmdline.server(), cmdline.user(), cmdline.pass());
	}
	catch (exception& er) {
		cerr << "Connection failed: " << er.what() << endl;
		return 1;
	}
	
	// Create new sample database, or re-create it.  We suppress
	// exceptions, because it's not an error if DB doesn't yet exist.
	bool new_db = false;

	{
		mysqlpp::NoExceptions ne(con);
		mysqlpp::Query query = con.query();
		if (con.select_db(mysqlpp::examples::db_name)) {
			// Toss old tables, ignoring errors because it would just
			// mean the table doesn't exist, which doesn't matter.
			cout << "Dropping existing sample data tables..." << endl;
			query.exec("drop table stock");
			query.exec("drop table images");
			query.exec("drop table deadlock_test1");
			query.exec("drop table deadlock_test2");
		}
		else {
			// Database doesn't exist yet, so create and select it.
			if (con.create_db(mysqlpp::examples::db_name) &&
					con.select_db(mysqlpp::examples::db_name)) {
				new_db = true;
			}
			else {
				cerr << "Error creating DB: " << con.error() << endl;
				return 1;
			}
		}
	}

	// Create sample data table within sample database.
	try {
		// Send the query to create the stock table and execute it.
		cout << "Creating stock table..." << endl;
		mysqlpp::Query query = con.query();
		query << 
				"CREATE TABLE stock (" <<
				"  item CHAR(30) NOT NULL, " <<
				"  num BIGINT NOT NULL, " <<
				"  weight DOUBLE NOT NULL, " <<
				"  price DECIMAL(6,2) NULL, " << // NaN & inf. == NULL
				"  sdate DATE NOT NULL, " <<
				"  description MEDIUMTEXT NULL) " <<
				"ENGINE = InnoDB " <<
				"CHARACTER SET utf8 COLLATE utf8_general_ci";
		query.execute();

		// Set up the template query to insert the data.  The parse()
		// call tells the query object that this is a template and
		// not a literal query string.
		query << "insert into %6:table values " <<
				"(%0q, %1q, %2, %3, %4q, %5q:desc)";
		query.parse();

		// Set a default for template query parameters "table" and "desc".
		query.template_defaults["table"] = "stock";
		query.template_defaults["desc"] = mysqlpp::null;

		// Notice that we don't give a sixth parameter in these calls,
		// so the default value of "stock" is used.  Also notice that
		// the first row is a UTF-8 encoded Unicode string!  All you
		// have to do to store Unicode data in recent versions of MySQL
		// is use UTF-8 encoding.
		cout << "Populating stock table..." << flush;
		query.execute("Nürnberger Brats", 97, 1.5, 8.79, "2005-03-10");
		query.execute("Pickle Relish", 87, 1.5, 1.75, "1998-09-04");
		query.execute("Hot Mustard", 73, .95, .97, "1998-05-25",
				"good American yellow mustard, not that European stuff");
		query.execute("Hotdog Buns", 65, 1.1, 1.1, "1998-04-23");

		// Test that above did what we wanted.
		cout << "inserted " << con.count_rows("stock") << " rows." << endl;

		// Now create empty images table, for testing BLOB and auto-
		// increment column features.
		cout << "Creating empty images table..." << endl;
		query.reset();		// forget template query info
		query << 
				"CREATE TABLE images (" <<
				"  id INT UNSIGNED AUTO_INCREMENT, " <<
				"  data BLOB, " <<
				"  PRIMARY KEY (id)" <<
				")";
		query.execute();

		// Create the tables used by examples/deadlock.cpp
		cout << "Creating deadlock testing tables..." << endl;
		query.execute("CREATE TABLE deadlock_test1 (x INT) ENGINE=innodb");
		query.execute("CREATE TABLE deadlock_test2 (x INT) ENGINE=innodb");
		query.execute("INSERT INTO deadlock_test1 VALUES (1);");
		query.execute("INSERT INTO deadlock_test2 VALUES (2);");

		// Report success
		cout << (new_db ? "Created" : "Reinitialized") <<
				" sample database successfully." << endl;
	}
	catch (const mysqlpp::BadQuery& er) {
		// Handle any query errors
		cerr << endl << "Query error: " << er.what() << endl;
		return 1;
	}
	catch (const mysqlpp::BadConversion& er) {
		// Handle bad conversions
		cerr << endl << "Conversion error: " << er.what() << endl <<
				"\tretrieved data size: " << er.retrieved <<
				", actual size: " << er.actual_size << endl;
		return 1;
	}
	catch (const mysqlpp::Exception& er) {
		// Catch-all for any other MySQL++ exceptions
		cerr << endl << "Error: " << er.what() << endl;
		return 1;
	}

	return 0;
}

Changes to test/ssqls2.cpp.

1
2
3
4

5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25

26
27
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
56





57
58


59

60
61








62






















63
64





65
66













67
68
69







70
71




72















73
74
75
76
77
78
79
80
81
82
83

84
85

86
87

88

89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
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

144
145

146
/***********************************************************************
 test/ssqls2.cpp - Tests the SSQLS v2 mechanism

 Copyright (c) 2009 by Warren Young.  Others may also hold copyrights

 on code in this file.  See the CREDITS.txt file in the top directory
 of the distribution for details.

 This file is part of MySQL++.

 MySQL++ is free software; you can redistribute it and/or modify it
 under the terms of the GNU Lesser General Public License as published
 by the Free Software Foundation; either version 2.1 of the License, or
 (at your option) any later version.

 MySQL++ is distributed in the hope that it will be useful, but WITHOUT
 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
 License for more details.

 You should have received a copy of the GNU Lesser General Public
 License along with MySQL++; if not, write to the Free Software
 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
 USA
***********************************************************************/


#include "../ssx/parsev2.h"

#include <mysql++.h>
#include <ssqls2.h>

#include <iostream>

using namespace std;


// Check that we can create a custom SSQLS v2 subclass by hand.  Tests






// for unexpected changes in SsqlsBase definition.
class TestSubclass : public mysqlpp::SsqlsBase





{


public:
	TestSubclass() :






	mysqlpp::SsqlsBase()
	{











































	}









































































	bool create_table(mysqlpp::Connection* conn = 0) const 
			{ (void)conn; return false; }





	std::ostream& equal_list(std::ostream& os,
			FieldSubset fs = fs_set) const












			{ (void)fs; return os; }

	std::ostream& name_list(std::ostream& os,
			FieldSubset fs = fs_set) const 












			{ (void)fs; return os; }

















	bool populated(FieldSubset fs = fs_all) const












			{ (void)fs; return false; }


	std::ostream& value_list(std::ostream& os,
			FieldSubset fs = fs_set) const 





			{ (void)fs; return os; }
};





// Test a single string to ParseV2::Field::Type value conversion








static bool






















Test(const char* input_type, const ParseV2::Field::Type& expected_value)
{





	ParseV2::Field::Type actual_value(input_type);
	if (actual_value == expected_value) {













		return true;
	}
	else {







		std::cerr << '"' << input_type << "\" converted to " <<
				int(actual_value) << " not " <<




				int(expected_value) << " as expected!" << std::endl;















		return false;
	}
}


// Test as many string to ParseV2::Field::Type value conversions as we
// expect the smart enum to support.
static bool
TestFieldTypeConversions()
{
	return 

		// First, test all the known "sane" inputs
		Test("bigblob", ParseV2::Field::Type::ft_blob) &&

		Test("bigint", ParseV2::Field::Type::ft_bigint) &&
		Test("bigtext", ParseV2::Field::Type::ft_string) &&

		Test("blob", ParseV2::Field::Type::ft_blob) &&

		Test("bool", ParseV2::Field::Type::ft_tinyint) &&
		Test("boolean", ParseV2::Field::Type::ft_tinyint) &&
		Test("char", ParseV2::Field::Type::ft_string) &&
		Test("date", ParseV2::Field::Type::ft_date) &&
		Test("datetime", ParseV2::Field::Type::ft_datetime) &&
		Test("decimal", ParseV2::Field::Type::ft_double) &&
		Test("double", ParseV2::Field::Type::ft_double) &&
		Test("enum", ParseV2::Field::Type::ft_string) &&
		Test("fixed", ParseV2::Field::Type::ft_double) &&
		Test("float", ParseV2::Field::Type::ft_float) &&
		Test("float4", ParseV2::Field::Type::ft_float) &&
		Test("float8", ParseV2::Field::Type::ft_float) &&
		Test("int", ParseV2::Field::Type::ft_mediumint) &&
		Test("int1", ParseV2::Field::Type::ft_tinyint) &&
		Test("int2", ParseV2::Field::Type::ft_smallint) &&
		Test("int3", ParseV2::Field::Type::ft_mediumint) &&
		Test("int4", ParseV2::Field::Type::ft_mediumint) &&
		Test("int8", ParseV2::Field::Type::ft_bigint) &&
		Test("mediumblob", ParseV2::Field::Type::ft_blob) &&
		Test("mediumint", ParseV2::Field::Type::ft_mediumint) &&
		Test("mediumtext", ParseV2::Field::Type::ft_string) &&
		Test("numeric", ParseV2::Field::Type::ft_double) &&
		Test("set", ParseV2::Field::Type::ft_set) &&
		Test("smallblob", ParseV2::Field::Type::ft_blob) &&
		Test("smallint", ParseV2::Field::Type::ft_smallint) &&
		Test("smalltext", ParseV2::Field::Type::ft_string) &&
		Test("text", ParseV2::Field::Type::ft_string) &&
		Test("time", ParseV2::Field::Type::ft_time) &&
		Test("timestamp", ParseV2::Field::Type::ft_datetime) &&
		Test("tinyblob", ParseV2::Field::Type::ft_blob) &&
		Test("tinyint", ParseV2::Field::Type::ft_tinyint) &&
		Test("tinytext", ParseV2::Field::Type::ft_string) &&
		Test("varbinary", ParseV2::Field::Type::ft_blob) &&
		Test("varchar", ParseV2::Field::Type::ft_string) &&
		// Test that it's properly case-insensitive
		Test("Numeric", ParseV2::Field::Type::ft_double) &&
		Test("sEt", ParseV2::Field::Type::ft_set) &&
		Test("SMALLBLOB", ParseV2::Field::Type::ft_blob) &&
		// Test that mildly bogus conversions are handled sanely
		Test("char(8)", ParseV2::Field::Type::ft_string) &&
		Test("decimal(16)", ParseV2::Field::Type::ft_double) &&
		Test("int5", ParseV2::Field::Type::ft_mediumint) &&
		Test("varchar(32)", ParseV2::Field::Type::ft_string) &&
		// Test that truly bogus stuff gets treated as stringish
		Test("varwhatsit(64)", ParseV2::Field::Type::ft_string) &&
		Test("klH54%KJgh^7hh4jvwtt", ParseV2::Field::Type::ft_string) &&
		true;
}





int
main()


{
	// Force instantiation of custom subclass
	TestSubclass tsc;


	return TestFieldTypeConversions() ? 0 : 1;

}

|

|
>
|
|



















>
|

|
|
<
|



>
|
>
>
>
>
>
>
|
|
>
>
>
>
>

>
>
|
|
>
>
>
>
>
>
|
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
>
|
|
>
>
>
>
>
|
|
>
>
>
>
>
>
>
>
>
>
>
>
|
>
|
|
>
>
>
>
>
>
>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
|
>
>
|
|
>
>
>
>
>
|
|
>
>
|
>
|
|
>
>
>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
|
>
>
>
>
>
|
|
>
>
>
>
>
>
>
>
>
>
>
>
>



>
>
>
>
>
>
>
|
|
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>





<
<
|
|

|
>
|
|
>
|
<
>
|
>
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
|
>
>
|
>
|
|
|
>
>

<
<
>
|
|
>
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
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
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
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
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
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
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
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
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
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
372
373
374
375
376
377
378
379
380


381
382
383
384
385
/***********************************************************************
 connection.cpp - Implements the Connection class.

 Copyright (c) 1998 by Kevin Atkinson, (c) 1999-2001 by MySQL AB, and
 (c) 2004-2008 by Educational Technology Resources, Inc.  Others may
 also hold copyrights on code in this file.  See the CREDITS.txt file
 in the top directory of the distribution for details.

 This file is part of MySQL++.

 MySQL++ is free software; you can redistribute it and/or modify it
 under the terms of the GNU Lesser General Public License as published
 by the Free Software Foundation; either version 2.1 of the License, or
 (at your option) any later version.

 MySQL++ is distributed in the hope that it will be useful, but WITHOUT
 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
 License for more details.

 You should have received a copy of the GNU Lesser General Public
 License along with MySQL++; if not, write to the Free Software
 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
 USA
***********************************************************************/

#define MYSQLPP_NOT_HEADER
#include "connection.h"

#include "dbdriver.h"
#include "query.h"

#include "result.h"

using namespace std;

namespace mysqlpp {

Connection::Connection(bool te) :
OptionalExceptions(te),
driver_(new DBDriver()),
copacetic_(true)
{
}


Connection::Connection(const char* db, const char* server,
		const char* user, const char* password, unsigned int port) :
OptionalExceptions(),
driver_(new DBDriver()),
copacetic_(true)
{
	connect(db, server, user, password, port);
}


Connection::Connection(const Connection& other) :
OptionalExceptions(other.throw_exceptions()),
driver_(new DBDriver(*other.driver_))
{
	copy(other);
}


Connection::~Connection()
{
	disconnect();
	delete driver_;
}


void
Connection::build_error_message(const char* core)
{
	error_message_ = "Can't ";
	error_message_ += core;
	error_message_ += " while disconnected";
}


std::string
Connection::client_version() const
{
	return driver_->client_version();
}


bool
Connection::connect(const char* db, const char* server,
		const char* user, const char* password, unsigned int port)
{
	// Figure out what the server parameter means, then try to establish
	// the connection.
	error_message_.clear();
	string host, socket_name;
	copacetic_ = parse_ipc_method(server, host, port, socket_name) &&
			driver_->connect(host.c_str(),
			(socket_name.empty() ? 0 : socket_name.c_str()), port, db,
			user, password);

	// If it failed, decide how to tell the user
	if (!copacetic_ && throw_exceptions()) {
		throw ConnectionFailed(error(), errnum());
	}
	else {
		return copacetic_;
	}
}


bool
Connection::connected() const
{
	return driver_->connected();
}


void
Connection::copy(const Connection& other)
{
	error_message_.clear();
	set_exceptions(other.throw_exceptions());
	driver_->copy(*other.driver_);
}


ulonglong
Connection::count_rows(const std::string& table)
{
	error_message_.clear();
	Query q(this, throw_exceptions());
	q << "SELECT COUNT(*) FROM `" << table << '`';
	if (StoreQueryResult res = q.store()) {
		return res[0][0];
	}
	else {
		return 0;
	}
}


bool
Connection::create_db(const std::string& db)
{
	error_message_.clear();
	Query q(this, throw_exceptions());
	q << "CREATE DATABASE `" << db << '`';
	return q.exec();
}


void
Connection::disconnect()
{
	error_message_.clear();
	driver_->disconnect();
}


bool
Connection::drop_db(const std::string& db)
{
	error_message_.clear();
	Query q(this, throw_exceptions());
	q << "DROP DATABASE `" << db << '`';
	return q.exec();
}


int
Connection::errnum()
{
	return driver_->errnum();
}


const char*
Connection::error() const
{
	return error_message_.size() ? error_message_.c_str() : driver_->error();
}


std::string
Connection::ipc_info() const
{
	return driver_->ipc_info();
}


bool
Connection::kill(unsigned long tid) const
{
	error_message_.clear();
	return driver_->kill(tid);
}


Connection&
Connection::operator=(const Connection& rhs)
{
	copy(rhs);
	return *this;
}


bool
Connection::parse_ipc_method(const char* server, std::string& host,
		unsigned int& port, std::string& socket_name)
{
	// NOTE: This routine has no connection type knowledge.  It can only
	// recognize a 0 value for the server parameter.  All substantial
	// tests are delegated to our specialized subclasses, which figure
	// out what kind of connection the server address denotes.  We do
	// the platform-specific tests first as they're the most reliable.
	
	if (server == 0) {
		// Just take all the defaults
		return true;
	}
	else if (WindowsNamedPipeConnection::is_wnp(server)) {
		// Use Windows named pipes
		host = server;
		return true;
	}
	else if (UnixDomainSocketConnection::is_socket(server)) {
		// Use Unix domain sockets
		socket_name = server;
		return true;
	}
	else {
		// Failing above, it can only be some kind of TCP/IP address.
		host = server;
		return TCPConnection::parse_address(host, port, error_message_);
	}
}


bool
Connection::ping()
{
	if (connected()) {
		error_message_.clear();
		return driver_->ping();
	}
	else {
		// Not connected, and we've forgotten everything we need in
		// order to re-connect, if we once were connected.
		build_error_message("ping database server");
		return false;
	}
}


int
Connection::protocol_version() const
{
	return driver_->protocol_version();
}


Query
Connection::query(const char* qstr)
{
	return Query(this, throw_exceptions(), qstr);
}


Query
Connection::query(const std::string& qstr)
{
	return query(qstr.c_str());
}


bool
Connection::select_db(const std::string& db)
{
	error_message_.clear();
	if (connected()) {
		if (driver_->select_db(db.c_str())) {
			return true;
		}
		else {
			if (throw_exceptions()) {
				throw DBSelectionFailed(error(), errnum());
			}
			return false;
		}
	}
	else {
		build_error_message("select a database");
		if (throw_exceptions()) {
			throw DBSelectionFailed(error_message_.c_str());
		}
		return false;
	}
}


std::string
Connection::server_status() const
{
	return driver_->server_status();
}


std::string
Connection::server_version() const
{
	return driver_->server_version();
}


bool
Connection::set_option(Option* o)
{
	const std::type_info& oti = typeid(*o);
	if (driver_->set_option(o)) {
		error_message_.clear();
		return true;
	}
	else {
		error_message_ = driver_->error();
		if (throw_exceptions()) {
			throw BadOption(error_message_, oti);
		}
		return false;
	}
}


bool
Connection::shutdown()
{
	error_message_.clear();
	if (connected()) {
		if (driver_->shutdown()) {
			return true;
		}
		else {
			if (throw_exceptions()) {
				throw ConnectionFailed(error(), errnum());
			}
			return false;
		}
	}
	else {
		build_error_message("shutdown database server");
		if (throw_exceptions()) {
			throw ConnectionFailed(error_message_.c_str());
		}
		return false;
	}
}




bool
Connection::thread_aware()
{
	return DBDriver::thread_aware();
}


void
Connection::thread_end()

{
	DBDriver::thread_end();
}
















































unsigned long
Connection::thread_id()
{
	return driver_->thread_id();
}


bool
Connection::thread_start()
{


	return DBDriver::thread_start();
}

} // end namespace mysqlpp

Changes to test/string.cpp.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
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
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
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
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
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
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
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
/***********************************************************************
 test/string.cpp - Tests the behavior of mysqlpp::String, particularly
	its data conversion methods.

 Copyright (c) 2007-2008 by Educational Technology Resources, Inc.
 Others may also hold copyrights on code in this file.  See the
 CREDITS.txt file in the top directory of the distribution for details.

 This file is part of MySQL++.

 MySQL++ is free software; you can redistribute it and/or modify it
 under the terms of the GNU Lesser General Public License as published
 by the Free Software Foundation; either version 2.1 of the License, or
 (at your option) any later version.

 MySQL++ is distributed in the hope that it will be useful, but WITHOUT
 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
 License for more details.

 You should have received a copy of the GNU Lesser General Public
 License along with MySQL++; if not, write to the Free Software
 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
 USA
***********************************************************************/

#include <mysql++.h>

#include <iostream>


// Does an equality comparison on the value, forcing the string to
// convert itself to T on the way.  Note that we do this test in terms
// of greater and less than to avoid pedantic GCC warnings for the
// floating point type tests.
template <typename T>
static bool
test_equality(const mysqlpp::String& s, T value)
{
	T converted = s.conv(value);
	if ((value < converted) || (value > converted)) {
		std::cerr << "Type conversion to " << typeid(T).name() <<
				" failed: \"" << s << "\" != \"" << value << "\"." <<
				std::endl;
		return false;
	}
	else {
		return true;
	}
}


// Check that we can convert strings with decimals in them to native
// floating-point values, regardless of locale.
static bool
test_float_conversion()
{
	// This stuff should just work
	if (!test_equality(mysqlpp::String("123.00"), 123)) return false;
	if (!test_equality(mysqlpp::String("123."), 123)) return false;

	// This is trickier: MySQL ignores the system locale when it comes
	// to decimal separators, always using '.', so ensure the conversion
	// stuff in MySQL++ does the right thing regardless.  Test against
	// this system's current locale, an arbitrary European one where ','
	// is the decimal separator, and the "C" locale where it's '.'.
	if (!test_equality(mysqlpp::String("621.200"), 621.2)) return false;
	std::locale old_locale = std::locale::global(std::locale::classic());
	if (!test_equality(mysqlpp::String("621.200"), 621.2)) return false;
	try {
		std::locale::global(std::locale("de_DE"));
		if (!test_equality(mysqlpp::String("621.200"), 621.2)) return false;
	}
	catch (std::runtime_error& e) {
		std::cerr << "WARNING: skipping European locale string "
				"conversion test:" << std::endl;
		std::cerr << "\t" << e.what() << std::endl;
	}
	std::locale::global(old_locale);

	// Check that we choke on silly float-like values
	try {
		if (test_equality(mysqlpp::String("621.20.0"), 621.2)) {
			std::cerr << "Quasi-FP with two decimal points "
					"converting without error!" << std::endl;
		}
		return false;
	}
	catch (const mysqlpp::BadConversion&) {
		return true;
	}
}


// Tries to convert the given string to an int.  Returns false if we got
// a BadConversion exception and didn't expect it, or didn't get one we
// expected.  Returns false on all other exceptions regardless.
static bool
test_int_conversion(const mysqlpp::String& s, bool throw_expected)
{
	// Try the conversion
	bool conv_threw = false;
	try {
		int converted = s;
		(void)converted;	// pedantic warning squisher
	}
	catch (const mysqlpp::BadConversion&) {
		conv_threw = true;
	}
	catch (const std::exception& e) {
		std::cerr << "Unexpected " << typeid(e).name() <<
				" exception in test_int_conv: " << e.what() << std::endl;
		return false;
	}
	catch (...) {
		std::cerr << "Like, totally bogus exception in test_int_conv, "
				"man!" << std::endl;
		return false;
	}

	// Did it do what we expected?
	if (throw_expected == conv_threw) {
		return true;
	}
	else {
		std::cerr << "Conversion of \"" << s << "\" to int " <<
				(conv_threw ? "did not throw" : "threw") << "; " <<
				(throw_expected ? "did not expect" : "expected") <<
				" it to." << std::endl;
		return false;
	}
}


// Checks that String's null comparison methods work right
static bool
test_null()
{
	mysqlpp::String not_null("", mysqlpp::mysql_type_info::string_type, false);
	mysqlpp::String is_null("", mysqlpp::mysql_type_info::string_type, true);
	if (not_null.is_null() == true) {
		std::cerr << "not_null.is_null() == true!" << std::endl;
		return false;
	}
	else if (not_null == mysqlpp::null) {
		std::cerr << "not_null == mysqlpp:null!" << std::endl;
		return false;
	}
	else if (is_null.is_null() == false) {
		std::cerr << "is_null.is_null() == false!" << std::endl;
		return false;
	}
	else if (is_null != mysqlpp::null) {
		std::cerr << "is_null != mysqlpp:null!" << std::endl;
		return false;
	}
	else {
		return true;
	}
}


// Ensures numeric conversions of many different types get handled
// correctly.
static bool
test_numeric(const mysqlpp::String& s, int value)
{
	return	test_equality(s, static_cast<signed char>(value)) &&
			test_equality(s, static_cast<unsigned char>(value)) &&
			test_equality(s, static_cast<signed short>(value)) &&
			test_equality(s, static_cast<unsigned short>(value)) &&
			test_equality(s, static_cast<signed int>(value)) &&
			test_equality(s, static_cast<unsigned int>(value)) &&
			test_equality(s, static_cast<signed long>(value)) &&
			test_equality(s, static_cast<unsigned long>(value)) &&
#if !defined(NO_LONG_LONGS)
			test_equality(s, static_cast<mysqlpp::longlong>(value)) &&
			test_equality(s, static_cast<mysqlpp::ulonglong>(value)) &&
#endif
			test_equality(s, static_cast<float>(value)) &&
			test_equality(s, static_cast<double>(value));
}


static bool
test_quote_q(const mysqlpp::String& s, bool expected)
{
	if (s.quote_q() == expected) {
		return true;
	}
	else {
		std::cerr << s.type().name() << " should" <<
				(expected ? "" : " NOT") << " be quoted." << std::endl;
		return false;
	}
}


// Similar to test_equality, but only works with std::string
// comparisons, which uses String::operator ==()
static bool
test_string_equality(const mysqlpp::String& s, std::string value)
{
	if (s == value) {
		if (s != value) {
			std::cerr << "String(\"" << s << "\") != std::string(\"" <<
					value << "\"), case 2!" << std::endl;
			return false;
		}
		else {
			return true;
		}
	}
	else {
		std::cerr << "String(\"" << s << "\") != std::string(\"" <<
				value << "\"), case 1!" << std::endl;
		return false;
	}
}


// Same as above, but for two String objects
static bool
test_string_equality(const mysqlpp::String& s1,
		const mysqlpp::String s2)
{
	if (s1 == s2) {
		return true;
	}
	else {
		std::cerr << "String(\"" << s1 << "\") != String(\"" <<
				s2 << "\"), but should be equal!" << std::endl;
		return false;
	}
}


// Inverse of above.
static bool
test_string_inequality(const mysqlpp::String& s1,
		const mysqlpp::String& s2)
{
	if (s1 != s2) {
		return true;
	}
	else {
		std::cerr << "String(\"" << s1 << "\") == String(\"" <<
				s2 << "\") but shouldn't be!" << std::endl;
		return false;
	}
}


int
main(int, char* argv[])
{
	try {
		int failures = 0;
		mysqlpp::String definit;
		mysqlpp::String empty("");
		mysqlpp::String zero("0");
		mysqlpp::String nonzero("42");
		mysqlpp::String intable1("42.");
		mysqlpp::String intable2("42.0");
		mysqlpp::String nonint("42.1");

		failures += test_equality(definit, mysqlpp::Date()) == false;
		failures += test_equality(definit,
				mysqlpp::DateTime(0, 0, 0, 0, 0, 0)) == false;
		failures += test_equality(definit, mysqlpp::Time()) == false;
		failures += test_equality(definit, false) == false;
		failures += test_equality(nonzero, true) == false;
		failures += test_numeric(definit, 0) == false;
		failures += test_numeric(zero, 0) == false;
		failures += test_numeric(nonzero, 42) == false;
		failures += test_quote_q(definit, true) == false;
		failures += test_quote_q(mysqlpp::String("1", typeid(int)),
				false) == false;
		failures += test_float_conversion() == false;
		failures += test_float_conversion() == false;
		failures += test_int_conversion(definit, false) == false;
		failures += test_int_conversion(zero, false) == false;
		failures += test_int_conversion(nonzero, false) == false;
		failures += test_int_conversion(intable1, false) == false;
		failures += test_int_conversion(intable2, false) == false;
		failures += test_int_conversion(nonint, true) == false;
		failures += test_null() == false;
		failures += test_string_equality(definit, empty) == false;
		failures += test_string_equality(empty, definit) == false;
		failures += test_string_equality(definit, "") == false;
		failures += test_string_equality(zero, "0") == false;
		failures += test_string_inequality(definit, zero) == false;
		failures += test_string_inequality(zero, definit) == false;
		failures += test_string_inequality(empty, nonzero) == false;
		
		return failures;
	}
	catch (mysqlpp::Exception& e) {
		std::cerr << "Unexpected MySQL++ exception caught in " <<
				argv[0] << ": " << e.what() << std::endl;
		return 1;
	}
	catch (std::exception& e) {
		std::cerr << "Unexpected C++ exception caught in " <<
				argv[0] << ": " << e.what() << std::endl;
		return 1;
	}

}

<
<
<
|
<
<
<

<
|
<
<
<
<
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
|
<
|
<
<
<
<
<
<
<
<
<
<
<
<
|
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
|
<
<
<
<
|
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
|
|
<
<
<
<
<
<
<
<
<
<
<
<
|
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<




1



2

3




4






























































5

6












7
8

























9



































10




11
12




















13
14












15
16















































































































17



<?xml version="1.0" encoding="utf-8"?>





<!-- XSL stylesheet containing things common to both HTML and FO




     transformations. -->
































































<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">












  <xsl:param name="section.autolabel" select="1"/>
  <xsl:param name="section.autolabel.max.depth" select="2"/>

























  <xsl:param name="toc.section.depth" select="2"/>








































  <!-- Hack to let us get <mathphrase>-like behavior in DB 4.2 -->
  <!-- From: http://www.sagehill.net/docbookxsl/Math.html -->




















  <xsl:template match="phrase[@role = 'math']">
    <xsl:call-template name="inline.italicseq"/>












  </xsl:template>
</xsl:stylesheet>
















































































































Changes to test/tcp.cpp.

1
2
3

4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
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
56
57
58
59
60
61
62

63
64
65
66
67
68
69

70
71
72
73

74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108

109
110
111

/***********************************************************************
 test/tcp.cpp - Tests the address parser/verifier in TCPConnection.


 Copyright (c) 2007 by Educational Technology Resources, Inc.
 Others may also hold copyrights on code in this file.  See the
 CREDITS.txt file in the top directory of the distribution for details.

 This file is part of MySQL++.

 MySQL++ is free software; you can redistribute it and/or modify it
 under the terms of the GNU Lesser General Public License as published
 by the Free Software Foundation; either version 2.1 of the License, or
 (at your option) any later version.

 MySQL++ is distributed in the hope that it will be useful, but WITHOUT
 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
 License for more details.

 You should have received a copy of the GNU Lesser General Public
 License along with MySQL++; if not, write to the Free Software
 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
 USA
***********************************************************************/

#include <exceptions.h>
#include <tcp_connection.h>

#include <iostream>
#include <sstream>


static void
test(const char* addr_svc, unsigned int port, const char* exp_addr,
		unsigned int exp_port)
{
	std::string addr(addr_svc), error;

	mysqlpp::TCPConnection::parse_address(addr, port, error);
	if (error.size()) {
		throw mysqlpp::SelfTestFailed("TCP address parse error: " +
				error);
	}
	else if (addr.compare(exp_addr) != 0) {
		std::ostringstream outs;
		outs << "TCP address parse mismatch: '" << addr << "' != '" <<
				exp_addr << "'";
		throw mysqlpp::SelfTestFailed(outs.str());
	}
	else if (port != exp_port) {
		std::ostringstream outs;
		outs << "TCP port parse mismatch: '" << port << "' != '" <<
				exp_port << "'";
		throw mysqlpp::SelfTestFailed(outs.str());
	}
}


static void
fail(const char* addr_svc, unsigned int port, const char* exp_addr,
		unsigned int exp_port)
{

	try {
		test(addr_svc, port, exp_addr, exp_port);
	}
	catch (...) {
		return;		// eat expected error
	}


	std::ostringstream outs;
	outs << "'" << addr_svc << "' == ('" << exp_addr <<
			"', " << exp_port << ") but should not.";
	throw mysqlpp::SelfTestFailed(outs.str());

}


int
main()
{
	try {
		// Domain name and IPv4 literal tests
		test(":", 0, "", 0);
		test("1.2.3.4", 0, "1.2.3.4", 0);
		test("1.2.3.4:", 0, "1.2.3.4", 0);
		test("1.2.3.4:567", 0, "1.2.3.4", 567);
		test("1.2.3.4", 890, "1.2.3.4", 890);
		test("1.2.3.4:telnet", 0, "1.2.3.4", 23);
		test("a.b.com", 0, "a.b.com", 0);
		test("a.b.com", 987, "a.b.com", 987);
		fail("@", 0, "@", 0);
		fail("::", 0, "", 0);
		fail(":", 0, "1.2.3.4", 45);
		fail("a.b.com::", 0, "a.b.com", 0);
		fail("a.b:com:1", 0, "a.b.com", 1);

		// IPv6 literal tests
		test("[]:123", 0, "", 123);
		test("[::]:telnet", 0, "::", 23);

		std::cout << "TCP address parsing passed." << std::endl;
		return 0;
	}
	catch (mysqlpp::SelfTestFailed& e) {
		std::cerr << "TCP address parse error: " << e.what() << std::endl;
		return 1;
	}
	catch (std::exception& e) {
		std::cerr << "Unexpected test failure: " << e.what() << std::endl;

		return 2;
	}
}


|

>
|
|
|



















|
|

|
|

|
<
<
<
|
<
|
<
<
<
<
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
|
|
<

>
|
<
<
<
<
<

>
|
<
<
|
>
|
|

<
<
|
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
|
<
<
<
|
<
<
<
<
<
<
<
|
<
>
|
|
|
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
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
56
57
58
59
/***********************************************************************
 field_names.cpp - Implements the FieldNames class.

 Copyright (c) 1998 by Kevin Atkinson, (c) 1999-2001 by MySQL AB, and
 (c) 2004-2007 by Educational Technology Resources, Inc.  Others may
 also hold copyrights on code in this file.  See the CREDITS file in
 the top directory of the distribution for details.

 This file is part of MySQL++.

 MySQL++ is free software; you can redistribute it and/or modify it
 under the terms of the GNU Lesser General Public License as published
 by the Free Software Foundation; either version 2.1 of the License, or
 (at your option) any later version.

 MySQL++ is distributed in the hope that it will be useful, but WITHOUT
 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
 License for more details.

 You should have received a copy of the GNU Lesser General Public
 License along with MySQL++; if not, write to the Free Software
 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
 USA
***********************************************************************/

#define MYSQLPP_NOT_HEADER
#include "common.h"

#include "field_names.h"
#include "result.h"

#include <algorithm>





namespace mysqlpp {




















void
FieldNames::init(const ResultBase* res)

{
	int num = res->num_fields();
	reserve(num);






	for (int i = 0; i < num; i++) {
		std::string p(res->fields().at(i).name());


		str_to_lwr(p);
		push_back(p);
	}
}




unsigned int














FieldNames::operator [](const std::string& s) const



{







	std::string temp(s);

	str_to_lwr(temp);
	return static_cast<unsigned int>(std::find(begin(), end(), temp) - begin());
}

} // end namespace mysqlpp

Changes to test/uds.cpp.

1
2
3
4
5
6
7
8
9
10
11
12
/***********************************************************************
 test/uds.cpp - Tests the Unix domain socket verifier in
	UnixDomainSocketConnection.  This test always succeeds on Windows!

 Copyright (c) 2007-2008 by Educational Technology Resources, Inc.
 Others may also hold copyrights on code in this file.  See the
 CREDITS.txt file in the top directory of the distribution for details.

 This file is part of MySQL++.

 MySQL++ is free software; you can redistribute it and/or modify it
 under the terms of the GNU Lesser General Public License as published

|
<

|







1
2

3
4
5
6
7
8
9
10
11
/***********************************************************************
 test/manip.cpp - Tests the quoting and escaping manipulators.


 Copyright (c) 2007 by Educational Technology Resources, Inc.
 Others may also hold copyrights on code in this file.  See the
 CREDITS.txt file in the top directory of the distribution for details.

 This file is part of MySQL++.

 MySQL++ is free software; you can redistribute it and/or modify it
 under the terms of the GNU Lesser General Public License as published
20
21
22
23
24
25
26
27
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
56
57














58
59
60


61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78






79



80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101











102










103
104
105
106
107
108
109
110
111

112
113

114
115

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
144
145
146
147
148
149
150
151
152


153
154

155
156
157
158

 You should have received a copy of the GNU Lesser General Public
 License along with MySQL++; if not, write to the Free Software
 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
 USA
***********************************************************************/

#include <connection.h>
#include <exceptions.h>

#include <iostream>
#include <sstream>
#include <string>

#if !defined(MYSQLPP_PLATFORM_WINDOWS)
#include <unistd.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/socket.h>
#include <sys/un.h>
#if !defined(AF_LOCAL)
#	define AF_LOCAL AF_UNIX
#endif


#include <errno.h>



#include <string.h>

static const char* success_path = "test_uds_success.sock";
static const char* failure_path = "test_uds_failure.sock";


static int
make_socket(const char* path, mode_t mode)
{
	// Just in case a socket with this name exists already, try to
	// remove it.  Only a failure if it exists and we can't remove it.
	if ((unlink(path) < 0) && (errno != ENOENT)) {
		return -1;
	}















	// Create the domain socket
	int fd = socket(AF_LOCAL, SOCK_STREAM, 0);


	if (fd < 0) {
		return -1;
	}
	
	// Bind the socket to the named file
	struct sockaddr_un saun;
	memset(&saun, 0, sizeof(saun));
	saun.sun_family = AF_LOCAL;
	strncpy(saun.sun_path, path, sizeof(saun.sun_path));
	saun.sun_path[sizeof(saun.sun_path) - 1] = '\0';
	if (bind(fd, reinterpret_cast<sockaddr*>(&saun), sizeof(saun)) < 0) {
		return -1;
	}

	// Change the socket's mode as requested
	if (chmod(path, mode) < 0) {
		return -1;
	}










	return fd;
}

	
static void
test_success()
{
	std::string error;
	int fd = make_socket(success_path, S_IREAD | S_IWRITE);
	if (fd >= 0) {
		bool fail = !mysqlpp::UnixDomainSocketConnection::is_socket(
				success_path, &error);
		if (fail) {
			throw mysqlpp::SelfTestFailed(error);
		}
	}
	else {
		std::ostringstream outs;
		outs << "Failed to create test domain socket: " << strerror(errno);
		throw mysqlpp::SelfTestFailed(outs.str());
	}
}























static void
test_failure()
{
	int fd = make_socket(failure_path, S_IREAD);
	if (fd < 0) {
		std::ostringstream outs;
		outs << "Failed to create test domain socket: " << strerror(errno);
		throw mysqlpp::SelfTestFailed(outs.str());

	}


	if (mysqlpp::UnixDomainSocketConnection::is_socket(failure_path)) {
		throw mysqlpp::SelfTestFailed("Failed to fail on read-only socket");

	}
	else if (mysqlpp::UnixDomainSocketConnection::is_socket(
			"BogusBogus.sock")) {
		throw mysqlpp::SelfTestFailed("Failed to fail on bad file name");
	}
	else {


		close(fd);
		unlink(failure_path);
		fd = creat(failure_path, S_IREAD | S_IWRITE);
		bool success = mysqlpp::UnixDomainSocketConnection::is_socket(
				failure_path);
		if (success) {
			throw mysqlpp::SelfTestFailed("Failed to fail on non-socket");
		}
	}
}
#endif











int
main()
{
#if defined(MYSQLPP_PLATFORM_WINDOWS)
	// Test not appropriate to this platform.  Always succeed.
	return 0;
#else
	try {
		test_success();
		unlink(success_path);
		test_failure();
		unlink(failure_path);
		return 0;
	}
	catch (mysqlpp::SelfTestFailed& e) {
		std::cerr << "TCP address parse error: " << e.what() << std::endl;
		return 1;
	}


	catch (std::exception& e) {
		std::cerr << "Unexpected test failure: " << e.what() << std::endl;

		return 2;
	}
#endif
}







|
<





|
|
<
|
<
<
<
<
<
>
|
<
>
>
>
|
|
|
<

>
|
|

<
<
<
|
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
|
<
>
>
|
|

|
<
<
<
|
|
<
<
|

|
|
<
<
|
>
>
>
>
>
>
|
>
>
>
|
|
|
|
<
<
<
<
<
<
<
|
|
<
|
|
<
<
<
<
|
|
>
>
>
>
>
>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
|
<
<
|
<
<
|
|
|
>
|
|
>
|
|
>
|
<
<
<


>
>
|
<
<
<
|
<
<
|
|
|
|
>
>
>
>
>
>
>
>
>





|
<
<
<
|
<
<
<
<
<
|
|
<
|
<
>
>
|
|
>
|
|
<
|
19
20
21
22
23
24
25
26

27
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
56
57
58
59
60
61
62
63
64
65

66
67
68
69
70
71



72
73


74
75
76
77


78
79
80
81
82
83
84
85
86
87
88
89
90
91
92







93
94

95
96




97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
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
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

 You should have received a copy of the GNU Lesser General Public
 License along with MySQL++; if not, write to the Free Software
 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
 USA
***********************************************************************/

#include <mysql++.h>


#include <iostream>
#include <sstream>
#include <string>


template <class T>

static bool





is_quoted(const std::string& s, T orig_str, size_t orig_len)
{

	return (s.length() == (orig_len + 2)) &&
			(s.at(0) == '\'') &&
			(s.at(orig_len + 1) == '\'') &&
			(s.compare(1, orig_len, orig_str) == 0);
}



template <class T>
static bool
is_quoted(const std::string& s, mysqlpp::Null<T> orig_str, size_t orig_len)
{



	return is_quoted(s, orig_str.data, orig_len);
}


// Stringish types should be quoted when inserted into Query when an
// explicit quote manipulator is used.
template <class T>
static bool
explicit_query_quote(T test, size_t len)
{
	mysqlpp::Query q(0);
	q << mysqlpp::quote << test;
	if (!is_quoted(q.str(), test, len)) {
		std::cerr << "Explicit quote of " << typeid(test).name() <<
				" in Query failed: " << q.str() << std::endl;
		return false;
	}


	mysqlpp::SQLStream s(0);
	s << mysqlpp::quote << test;
	if (is_quoted(s.str(), test, len)) {
		return true;
	}
	else {



		std::cerr << "Explicit quote of " << typeid(test).name() <<
				" in Query failed: " << q.str() << std::endl;


		return false;
	}
}




// Nothing should be quoted when inserted into an ostream, even when an
// explicit quote manipulator is used.  The manipulators are only for
// use with Query streams.
template <class T>
static bool
no_explicit_ostream_quote(T test, size_t len)
{
	std::ostringstream outs;
	outs << mysqlpp::quote << test;
	if (!is_quoted(outs.str(), test, len)) {
		return true;
	}
	else {
		std::cerr << "Explicit quote of " << typeid(test).name() <<







				" in ostream erroneously honored!" << std::endl;
		return false;

	}
}






// Nothing should be implicitly quoted as of v3.  We used to do it for
// mysqlpp::String (formerly ColData) when inserted into Query, but
// that's a silly edge case.  The only time end-user code should be
// using Strings to build queries via the Query stream interface is when
// using BLOBs or when turning result set data back around in a new
// query.  In each case, there's no reason for String to behave
// differently from std::string, which has always had to be explicitly
// quoted.
template <class T>
static bool
no_implicit_quote(T test, size_t len)
{
	std::ostringstream outs;
	outs << test;
	if (!is_quoted(outs.str(), test, len)) {
		mysqlpp::Query q(0);
		q << test;
		if (is_quoted(q.str(), test, len)) {
			std::cerr << typeid(test).name() << " erroneously implicitly "
					"quoted in Query: " << outs.str() <<
					std::endl;
			return false;
		}





		mysqlpp::SQLStream s(0);
		s << test;
		if (!is_quoted(s.str(), test, len)) {
			return true;
		}
		else {
			std::cerr << typeid(test).name() << " erroneously implicitly "
					"quoted in Query: " << outs.str() <<
					std::endl;
			return false;
		}



	}
	else {
		std::cerr << typeid(test).name() << " erroneously implicitly "
				"quoted in ostringstream: " << outs.str() <<
				std::endl;



		return false;


	}
}


// Run all tests above for the given type
template <class T>
static bool
test(T test, size_t len)
{
	return explicit_query_quote(test, len) &&
			no_explicit_ostream_quote(test, len) &&
			no_implicit_quote(test, len);
}


int
main()
{
	char s[] = "Doodle me, James, doodle me!";



	const size_t len = strlen(s);






	int failures = 0;

	failures += test(s, len) == false;

	failures += test(static_cast<char*>(s), len) == false;
	failures += test(static_cast<const char*>(s), len) == false;
	failures += test(std::string(s), len) == false;
	failures += test(mysqlpp::SQLTypeAdapter(s), len) == false;
	failures += test(mysqlpp::Null<std::string>(s), len) == false;
	return failures;
}


Changes to test/wnp.cpp.

1
2
3
4

5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26



27
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

/***********************************************************************
 test/wnp.cpp - Tests WindowsNamedPipeConnection::is_wnp().  This test
	can only fail on Windows!  It succeeds when built for anything else.


 Copyright (c) 2007 by Educational Technology Resources, Inc.
 Others may also hold copyrights on code in this file.  See the
 CREDITS.txt file in the top directory of the distribution for details.

 This file is part of MySQL++.

 MySQL++ is free software; you can redistribute it and/or modify it
 under the terms of the GNU Lesser General Public License as published
 by the Free Software Foundation; either version 2.1 of the License, or
 (at your option) any later version.

 MySQL++ is distributed in the hope that it will be useful, but WITHOUT
 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
 License for more details.

 You should have received a copy of the GNU Lesser General Public
 License along with MySQL++; if not, write to the Free Software
 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
 USA
***********************************************************************/




#include <mysql++.h>

#include <iostream>
#include <sstream>



int
main()
{
#if defined(MYSQLPP_PLATFORM_WINDOWS)
	if (!mysqlpp::WindowsNamedPipeConnection::is_wnp(".")) {
		std::cerr << "Failed to identify Windows named pipe" << std::endl;

	
	}

	else if (mysqlpp::WindowsNamedPipeConnection::is_wnp("bogus")) {





		std::cerr << "Failed to fail for bogus named pipe" << std::endl;









	}
	else if (mysqlpp::WindowsNamedPipeConnection::is_wnp(0)) {







		std::cerr << "Failed to fail for null named pipe" << std::endl;
	}

	else {

		return 0;
	}

	return 1;

#else

	return 0;
#endif
}


|
|

>
|
|
|



















>
>
>



|

>


|

|
|
|
>
|
|
>
|
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
|
<
>
>
>
>
>
>
>
|
|
>
|
>
|
|

|
>
|
>
|
<
|
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
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
56
57
58
59
60
61
62
63
64

65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84

85
86
/***********************************************************************
 simple2.cpp - Retrieves the entire contents of the sample stock table
	using a "store" query, and prints it out.

 Copyright (c) 1998 by Kevin Atkinson, (c) 1999-2001 by MySQL AB, and
 (c) 2004-2009 by Educational Technology Resources, Inc.  Others may
 also hold copyrights on code in this file.  See the CREDITS.txt file
 in the top directory of the distribution for details.

 This file is part of MySQL++.

 MySQL++ is free software; you can redistribute it and/or modify it
 under the terms of the GNU Lesser General Public License as published
 by the Free Software Foundation; either version 2.1 of the License, or
 (at your option) any later version.

 MySQL++ is distributed in the hope that it will be useful, but WITHOUT
 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
 License for more details.

 You should have received a copy of the GNU Lesser General Public
 License along with MySQL++; if not, write to the Free Software
 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
 USA
***********************************************************************/

#include "cmdline.h"
#include "printdata.h"

#include <mysql++.h>

#include <iostream>
#include <iomanip>

using namespace std;

int
main(int argc, char *argv[])
{
	// Get database access parameters from command line
	mysqlpp::examples::CommandLine cmdline(argc, argv);
	if (!cmdline) {
		return 1;
	}

	// Connect to the sample database.
	mysqlpp::Connection conn(false);
	if (conn.connect(mysqlpp::examples::db_name, cmdline.server(),
			cmdline.user(), cmdline.pass())) {
		// Retrieve the sample stock table set up by resetdb
		mysqlpp::Query query = conn.query("select * from stock");
		mysqlpp::StoreQueryResult res = query.store();

		// Display results
		if (res) {
			// Display header
			cout.setf(ios::left);
			cout << setw(31) << "Item" <<
					setw(10) << "Num" <<
					setw(10) << "Weight" <<
					setw(10) << "Price" <<
					"Date" << endl << endl;


			// Get each row in result set, and print its contents
			for (size_t i = 0; i < res.num_rows(); ++i) {
				cout << setw(30) << res[i]["item"] << ' ' <<
						setw(9) << res[i]["num"] << ' ' <<
						setw(9) << res[i]["weight"] << ' ' <<
						setw(9) << res[i]["price"] << ' ' <<
						setw(9) << res[i]["sdate"] <<
						endl;
			}
		}
		else {
			cerr << "Failed to get stock table: " << query.error() << endl;
			return 1;
		}

		return 0;
	}
	else {
		cerr << "DB connection failed: " << conn.error() << endl;
		return 1;

	}
}

Changes to tools/tarballs-to-fossil.

1
2
3
4
5
6
7
8
9
10
11
12
13
14










































15
16
17
18
19
20
21

















































22
23
24
25
26
27
28
29
















































30
31















































32

33
34
35


36
37
38
39
40
#!/bin/bash
ignores="$(tr '\n' ',' < ../tb-ignore-glob)"
rdir=~/tangentsoft.com/mysql++/releases

set -e
ls $rdir/*.tar.gz | 
        ggrep -Po '\d[\d.]+\d[.a-f]{0,2}' | 
        sed -e 's/\.$//' |
        gsort -t. -k 1,1n -k 2,2n -k 3,3n -k 4,4n |
while read ver
do
    f=$(echo $rdir/*-${ver}.tar.gz)
    echo -e "\n----------------------------------------------------------"
    echo -e "Processing MySQL++ v$ver, $(basename $f)...\n"











































    find . -type f -not -name .fslckout -delete
    find . -type d -delete

    if gtar -x --strip-components=1 -f "$f"
    then
        fossil addremove --ignore "$ignores"


















































        if [ -e ChangeLog ]
        then
            newest=ChangeLog
        else
            newest=$(find . -type f -print0 | xargs -0 ls -t | head -n 2 | tail -1)
        fi
        mtime=$(date -u -r "$newest" +%FT%TZ)
















































        
        echo "Checking in MySQL++ v$ver, mtime=$mtime..."















































        fossil ci \

            --comment "Version $ver" \
            --date-override $mtime \
            --no-warnings \


            --tag "v$ver"
    fi
done

fossil ui
|
|
|
|
|
|
|
|
|
|
|
|
|
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
|
|
|
|
|
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
|
|
|
|
|
|
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
|
<
<
>
>
|
<
<
|
<
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
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
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
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
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
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220


221
222
223


224

C Added\stools/tarballs-to-fossil,\sthe\sBash\sscript\sused\sto\sconvert\sthe\narchive\sof\sMySQL++\starballs\sto\sFossil\smajor-version\scheckins\son\sthe\snew\nFossil\srepository.\s\sThis\sis\schecked\sin\safter\shopefully\sbecoming\sobsolete\nby\sway\sof\sdocumenting\show\sthe\sconversion\swas\sperformed.\n\nThis\scheckin\salso\sincludes\stools/tb-ignore-glob,\sthe\s"fossil\saddremove\n--ignore"\srule\sset\sused\sby\sthe\sscript,\swhich\sdocuments\swhich\sfiles\swere\nfiltered\sout\sof\sthe\starballs:\sbasically,\sany\sfile\sthat\scould\sbe\ngenerated\sfrom\sone\sof\sthe\sother\sfiles\sthat\swere\schecked\sin\sfor\sthat\nmajor\sversion.\n\nBecause\sthis\slist\scould\sbe\soverly\s"grabby,"\sparticularly\sfor\solder\nreleases\s(e.g.\s"Makefile"\sin\sthe\spre-Autoconf\sand\spre-Bakefile\sworlds)\nand\sbecause\smodern\ssystems\smay\snot\salways\sbe\sable\sto\srecreate\sgenerated\nfiles\sfrom\sthe\smore\santiquated\ssources\sin\sany\scase,\sthe\starballs\swill\nremain\sthe\sprimary\sdata\ssources.
D 2017-06-28T22:27:48.654
F Bakefiles.bkgen 1378c0673a35d047724db07b75b53dda4edac3532f50f287a286154c3068cac0
F COPYING.txt c943babbd1de963894a9ba8583e8f50cdc7a6ab7c0522a0251c8cd21caa9f672
F CREDITS.txt 9f8804156fe7d6266312bec64d810aeaa3b9cc683615619b8d8c63d18f806329
F ChangeLog 6acaeac4720a2ca7101d132025f77931e0a24f7b090259753d320149ebd2f6fb
F HACKERS.txt 6f1c4cfc77b41d80064c819f28eb77e732e7a9c3d0cee5bd64d8dd08b757b84c
F INSTALL.txt 34f34084bb61b1092c2baaba90fb48723010dbe50d09acb5b170820aafad41b5
F LICENSE.txt 97ebb45ce18ea0be5a31a8aec2228eee997e3ed3df0aa31771ade1999d483a82
F Makefile.mingw ff33376c786cc8ca277f7f00b87d343c2d2216e78c2473032c968890b34952f9
F Makefile.simple 194fd1ef9153e8483049ad1b860a396cd52fefa96e9c22d8b4554e32ddf222ab
F README-Cygwin.txt 4cd935634ed65db728aeab89c28bad971db4d02caa3db2f8c970e02396387f85
F README-Linux.txt 418e01796ed0bc9b54ac87aaf2d38da33845e26c10fb04e77a9e10ad2ee01fb2
F README-Mac-OS-X.txt e8bd6329fa524099e0e2ca7fc3e4576a0b0c1b7a6ce3fa562a144cce92f68d67
F README-MinGW.txt 5b4eaf81270ae701b2ba5b4eec5b3a9036b34cd429436c9eeb3b168e3ea32e2d
F README-Solaris.txt 17bab66b3620f84a1b18c99a88abf447d46ad915888485e8dc4ee6a3c7898c9e
F README-Unix.txt 65a51383a2c799e01c620c3175fead5a52ba031e22685b24c5730463a4763c8d
F README-Visual-C++.txt 2c1d8ffcf42241aacba78caf3c4bbc1b92ddbf887bfec9e2a28aacfb818a5e18
F README-examples.txt 1e9e6a1f8602029653bc44120a36c1e50fe583b5489639081f745255f18400a3
F README.txt beb3b1247585cc45b04d82a823dd81d43f81ff6e8a468d956d3a5d5b42fe93dd
F RELEASE-CHECKLIST.txt e8f52d5cb37b0e6797463d4c7d96f1afb1f9075f1b231aea82e256a8db924107
F Wishlist e3f928a53a316acb22276dd311c1b9d01521b23368c6c1218945a6a41b021fc7
F abi.xml.in b977dd2983a3b8e33d4330ba697a4c65ce21e7b58f79ee431c906d761a6a0894
F bk-deps a506e067bfde55305e097815f1e11febbcbaf9c0493ef804b4b81dfc1a60f34e x
F bmark.txt 973d955a0625b12f5f9045fb31b818c0d24a17926320c3e2a1a94e3d2f778c39
F bootstrap 8737ed93138ac7b4de5ef09bdd76b71fa77df6815c6f8829c7291316249e72b0 x
F bootstrap.bat 8c501dacd4993d4bdf43a67f1c6645b22c85fb03f36b423600a2a68c36ce75d2
F cleanmf e385426a032ada497be42ff7504ef1fffcccd34635af530c25f19e2f209ec653 x
F config.h.in 6a3905b06799612eeccaace5bc8881647034c0ce10746b8ae38eaa5cd6fe53a1
F config/acx_pthread.m4 8a9dbf4783b282f82c062edac20886e75e0ef9d555ac59b0dad68f1559a3a460
F config/autoconf_inc.m4 7d57c517f5a4ccd2a6d97c7904feaa2bc1089fa020e0e65b75f0b54e9a36adef
F config/libm.m4 de3dcf0b6e8149f13c9e26dcdeaf25bf5b40fa3993546835b29c0a3be6ee63ea
F config/localtime_r.m4 8ba2bda9bdf152d8f901180b2eec716f75c381c5ed2d98666f4f0cfe29152256
F config/mysql++.m4 a305b5d0f8c47b51e487381ef4e38f4acc63683b2d10c9c15065430044e4d207
F config/mysql_loc.m4 c3ea81a98f21fda675d34d1cd29fe6fecea7869b6231b048c3d76200db4522a1
F config/mysql_ssl.m4 4ef297a027b01f69e7e4669fdd2e86f1e8542b484fd37307c27da76525decdd5
F config/socket_nsl.m4 6dd364d066feec0abf2b2bcdd377710010c459d3c6fbedad77a20f38997c7de2
F config/stl_slist.m4 614e5c3929b7b506b1f61ce6a4f089a5ef5acc049a0920963a32dd2bd11ad7c1
F configure.ac 6d332cf654574ea85d0af26a091c017649a10141f8bce617c0766741e2ee64b0
F doc/README-devel-RPM.txt d920bb8de3af6578f5cbe1d41b53010b3e0c37163ec8226aa708d1aab869ec83
F doc/README-manuals-RPM.txt 12316b39e05f17d22d378647a574c7f6d1a12bca86ca75c54e761555b9f34763
F doc/ssqls-pretty d5f23af891a27583871e0bc1dd3c3df1f43eb6ce02e8ba06f69c3b5a82efedc5 x
F doc/userman/Makefile e13bd56940b7b3bf70f1c1a267deaec966286edff17f329b1a38118fd8226663
F doc/userman/Makefile.hello.mingw f7f55f4d2e735b1813dd24b742beacb5b60ddd36501ebb902bcf77ab0b723480 x
F doc/userman/Makefile.hello.posix 1d3246fbc93fa02e7a9b2e84ba0ef32f27213789e49e6a4c95ad05685b9b2ade
F doc/userman/breakages.dbx 79dec0d4506d735a4f1c8d0519bb5f3d03dbbf8b2be7c4f094a03f8166101905
F doc/userman/common.xsl ec35926ab1e3a6c06d2df9ddd383e6d6cc2736db2385b193d08802d9190d58ee
F doc/userman/configuration.dbx a9b31160135a6eaf2403e070b4467cb20eed36d1c199c2a5e72b2873303586f0
F doc/userman/fo.xsl ac5397b661eb25507f9709f3e420b0d6be899d5bbed5c2cbff5c76b1a09ceadc
F doc/userman/fo2pdf 794966e1df54ad60a05572f1ca73a978e4880d94c615d6ddeae0aa18a7d1cabd x
F doc/userman/html.xsl b249f6a6431880307f0e6c0081a507bd44df0e2358c50c41fa443a0dcf4675a3
F doc/userman/incorporating.dbx cb3499acc5d534729a94e6bfd552ffd5a56444232f0f9e28d61bcb715e2b8859
F doc/userman/intro.dbx a0e634330659449d3684ae2882e9a2d521a46a36382aefa4d04bd1bf49498eba
F doc/userman/licenses.dbx 9cbaec5d5d90c5af2f2ee9c9f15f022a7011508741c4feaf3f0f3fe8f1bb5fac
F doc/userman/mktxt d7fb06e2c293cb0106ec5ba5508757022740f07e79f96065925735fa11506374 x
F doc/userman/overview.dbx 6ceb7c85beab820f19c8c7ff1f42b542eeece43909aa0bbc3ca74df50ed1b44a
F doc/userman/section-template.dbx 258801d08cb6774a5063c2f92cfaec176712cf47f68641bf724e4a944c02c70a
F doc/userman/ssqls.dbx dfe80a00a0b7f9e9b6ede3e896ab024fd453aef189709986c19d95d5bf0de251
F doc/userman/threads.dbx baea8e064cb820c1c38886fe6862607d5d53897354a1306b9091036b362080ea
F doc/userman/tquery.dbx 13530007922f624dce13610e930cf9612966575ecb52ad578ba7cc410611c22e
F doc/userman/tutorial.dbx 3a460c4f3e66b1f9e32bdaac703a7241ff92becc9c88569928af7f800ae6fa1d
F doc/userman/unicode.dbx 245cca9ba6f1a8cbf6cf3113fd54594ed221e0fd65be60ef67d4852f7542f3db
F doc/userman/userman.dbx eeca4f9b77924de85ada2fd9b8c51769c111aa49b7de0439f2205bf760a26058
F doc/userman/userman.dbx.in 361a8b803a7c157233a627a91091b29c9dd500b0fa0a18105b2352332dc44703
F doc/userman/xinclude.mod b04b9b28807b9abb457dddd72d8df3548347c56dd5d69b97b762f457eabf01fe
F dtest 257ddf48697e9841107610031187e5c9676118fac4ba3de9e753140f91056001 x
F examples/cgi_jpeg.cpp 41c856cdd9a4c36f2130e08b11fae4a4983cf747282a50cbab99006d0bc1f5b1
F examples/cpool.cpp e695c44737d7b68dd6cfd562a8e82cddaf2a835b314d81b0fafec2ff29bc1858
F examples/dbinfo.cpp 9c73702befdd5ba82364634d47fefad8ef164d54dff80fce5bd6d2d67af70a1d
F examples/deadlock.cpp e2d48b901cb0c9ef8e2e18050754f874489fa76eb944b55e8120211ba5afbdd7
F examples/fieldinf.cpp b92f510ca75e331f27913c3da776f7dc4ea5e6a17e0ac9d39beb1b89806f2c3b
F examples/for_each.cpp 3efb48e69dc820480f465c4af927e12937b0df6e3345ea7ede39a22a3f34d2ff
F examples/images.h eff98d54763fcdc1ab8e58ab71648f74554d192b9d7bf99b93669de65e70fa30
F examples/load_jpeg.cpp 5259990f5295ef68299d39d229076fa6835d8eed9c050137e9b09bad4a142886
F examples/logo.jpg b551f2a4609684c83c17acc32faa08af659df397aba70fe7e0f12de82c4bc934
F examples/multiquery.cpp 76a2497c953e6495a46ef36bc817bee1bcadd55300f6db7afe9079e95d8fe871
F examples/printdata.cpp cabfdb65b121a0ada9cdd67379d458b8b77eb69d60a44a369c73dfa036700fc9
F examples/printdata.h 201ba1d04b99ef5db9d69d99f985d41fab983a12810c4e16b9a433287c92b483
F examples/resetdb.cpp ce468f1076cfee480664f6cd056aca95e6899ddaa6c89db65852a04f8267ecb4
F examples/simple1.cpp 8140c09587cebe3d8f97ae0dafe29188b5578d26d58adeb7c81e1f5faceb9a4b
F examples/simple2.cpp e4edb4d49033848ee82c54d5b6d46f3318bf44c56d5959719ab6f7eaa7f0da60
F examples/simple3.cpp 604fa7b0dc9b1f7677a7088493b8fa25014bc38f42f79f9002f95c63967c3389
F examples/ssqls1.cpp 26c1a1af36aebcfc6a0adeaedddbc3eb9bbd302933cdb50a5dc275146f03233a
F examples/ssqls2.cpp faead49be3a339b0817fa74b77f16240895cfa4ebbe85f067ad721e4b0475d61
F examples/ssqls3.cpp 5f776cd5de0a9e1b79b4431f66c89dabe26f52a205f0580a60703ce771c14a61
F examples/ssqls4.cpp 4a0ba3becc091fac4003ff905daef1f6644cc9e992b6714e525ac50ccaf472b9
F examples/ssqls5.cpp ed53e908e3206d61081485c8ac327abc237316240f047a91415a69a71bcd2e69
F examples/ssqls6.cpp 71a4d0b2256e288318dc460ba72e46a97c883451269148dc130757bd1f8cb886
F examples/stock.h 7a27e43688f7fb40e19ee36ae6637ad93aca88f4d72a45cc4fea06ffbcd77f1e
F examples/stock.txt 06d0d1f58e3017f8c63603197f581e7b7300fbd87a73f25cddca2d381bae1a6b
F examples/store_if.cpp 0adea2de699079171e50d65e77c67d768d0f0face939b59146e220a442d80358
F examples/threads.h 78091cf6989ba263082a8aade1b1fa1d64130f5e2d5e353e5afcbe7c6bb4fbed
F examples/tquery1.cpp 6c6965a13411541a923f44e69f442a53aadac50c49192963fb982c3aeeada802
F examples/tquery2.cpp 96a2a408d852707bcbd7f14cfa823fb8331763ac752b445e4f5acfc3bd3fb94e
F examples/tquery3.cpp e0e53072caeffe9e3944a3bbff081cc2751fe9342e15eb98168ef17fcfe686f7
F examples/tquery4.cpp 753892f736a61afa926cdb1eab7a34c1ebd6f4b5dcbb39b21aaafe50bed1c909
F examples/transaction.cpp d1b310ebbea4cfe14f7c8656db8485b8ab6416eb9912f7911001fad02db25d4e
F examples/vstudio/mfc/mfc.cpp 81bc84b78340d7e4fba2c850f4b25720ad7fcfb4d58fefe1cce3c3ed9bd2e019
F examples/vstudio/mfc/mfc.h e1da8ccc157701e5c208cf8b24b51cf08d8f13b48a8809d8223318ad813991ab
F examples/vstudio/mfc/mfc.rc 7f893118cb86cbcbf8a4d4d30fd5f122d7b7916895aba82327c770354dbd842a
F examples/vstudio/mfc/mfc_dlg.cpp 5b2eb625d7fb07648b9a0429490a0812b186e237b2cd690025f01483356cdaad
F examples/vstudio/mfc/mfc_dlg.h eb5ba79ffe166455e27601b94642566de7822a87329661abac15f4e200f7bb72
F examples/vstudio/mfc/resource.h ca71f958b51bf17dfbba0d1591211efe36187ef869b6bff5e0dc9a59cf40a2f6
F examples/vstudio/mfc/stdafx.h b5a1c41c2a252ab4275ec9d8a584f058c4596c2c6d767ee756a4f4546ea86fd1
F examples/vstudio/wforms/AssemblyInfo.cpp 08e3cfc50233132ea5d4b70b47fa2bce669c2c6a97896f8b0ec62b882e1deeb1
F examples/vstudio/wforms/MainForm.h 0f3c1f1f59d50683e262a07c2db28b2eba3dbcdc23f190354b18f7b41444781f
F examples/vstudio/wforms/MainForm.resX f69089f338845d493eccdd05a2650a7f3cca9f0993f746723d7f7d08054d681f
F examples/vstudio/wforms/resource.h 3c4a478a4643ae9ccf7988df1613197a7f4ab3483455c8037004c6da26b036e9
F examples/vstudio/wforms/wforms.cpp 6566a4a77faae13ee3bdd474c347a62e68632c5f6b053194aa40d12689e4a160
F exrun 4450f57cd0ed563925652e0fc3af646a0fa471138831c1e120ec534aa65dd948 x
F exrun.bat f1884f9c023c322373f814e7d70f6488771569f4035c7d1697d970b7bb9e893d x
F install.hta.in c154df770e08f8b617f9aed85dbfe54e2650e64ab63f6afb791a3a00829ed678
F lib/Doxyfile.in a6db5bb5742ae95b6e08f786265246e40a71442e06f3000b3eaa5b9abf0c2592
F lib/autoflag.h 666bc35155071fb9e34b8323eb94628a155b57a57d2430a4782a37e73660a333
F lib/beemutex.cpp 729da280560845acae28d48d5c01455713ef87c358637279600dc254442c19fc
F lib/beemutex.h a88f946fecfdf1f998a3fa1c33764cd8001e45fe17ee8c2db0cdc38dad54e4d7
F lib/cmdline.cpp 45184784697a5dae9bfcfc67a5aecf80e13b5149ea1f5d9ecd42ce88ab0aa417
F lib/cmdline.h 53678455c3bb2de7a6af5b89d539e5895ee99649a6183340778b8bbd9cbfe794
F lib/common.h d117dd0d31146fc428af817a3913e3e8aeccecd2312cef208b314c2d4523d3d5
F lib/comparable.h 4abef254c194319823ad527991d2f1065f24fc435439469e2c7795c8ba563471
F lib/connection.cpp 6c8731eea29ccf5e7edd8ebe839c20a90a30871ec38a0ad03e7db9faf0d89fdc
F lib/connection.h b76a8d178d4f1f730a9cab645112fcbfbba80c50e2bc2eca671527809febea18
F lib/cpool.cpp c7e9798763fb203a2a2b662371b5cd1f9a356551866f1f6f83c662bd5a4038d1
F lib/cpool.h 0f199b2b65847bb3b5e85388b505d3b6d1d0a16069256db3b6f46ea6f676f3f0
F lib/datetime.cpp efcef86ddea19a3d99db91df4d9816e5cd0cc6d044ecb774a41f8738006a5dfb
F lib/datetime.h 3a5f9ec152eace11864527c907bf8f9543bb96a939fb1f23a129133432ade11f
F lib/dbdriver.cpp 9816463fe0d0100cad12adfaa97b0cc5c443bf50493bc2e2eaea33359e4d87c0
F lib/dbdriver.h 4778a6b5e2ae6739d0f8868fb126728be4e9113813e711fd34a6a389b9c8fe3c
F lib/exceptions.h 45fc9a816fd4222661dce0b8f2649be7a9c22fdd9427e54dd8fd9b355939a53a
F lib/field.h 0e52ca8dc9377690ca6f0ae8a70a0840ddaa9132eba233ea1f558a00a74b748d
F lib/field_names.cpp 5b07458d72e3b75703dc0a499be7788470c1999fd66bd979d7c05a6a1b078e00
F lib/field_names.h 0291d3307f2b96f3a71dfb0ebaa14598f3152a48bfbb9eaab798bbe4e7700182
F lib/field_types.cpp f398720812c018c158c218a6e22959c908973ede7231dcb76b7bede546b8b16d
F lib/field_types.h f42e8d92974d7043b5f82e7c6f9772f0a05e61bfba7fa7761a2427c306beea18
F lib/insertpolicy.h a05b622f47e2fc343f488db2a89c2115a8a818a0ce7cc31a4567f0a0b38beb1a
F lib/manip.cpp 9dc4486fde9f360bcf05497bfca1dc95ad7d2367c5806240dfd76f48d2af56a8
F lib/manip.h ec92e560792a7ae7418e6f766fc2ca70efb6d6c2892707bf1c2fa152e4e8c370
F lib/myset.cpp 462c808158c304a45340a3bcb04bbfe25ecc36103ad2b88812f2efe7b1cd9f00
F lib/myset.h 24521ab1b8db1aa23215d8f7132235107921ff5f97998139080325518c49a9b1
F lib/mysql++.cpp b6a0f2325a8c5fa6d3483c95ff64130de75b82ae090505ccb6a434d9332553f1
F lib/mysql++.h.in 66adebeaff1ad5a4a48ec252d2afc391519d7e4c89c6087ff90aff57310d34ed
F lib/mystring.cpp 91086ed3a3bd79e622c3de4c440f5e83260147b7c4ea641bfdbb3a0001bce2d2
F lib/mystring.h 73a5dcf949b42550ac639ff2d846826ef53634d73238f7caa696242ef035eb46
F lib/noexceptions.h 90b154a5656a36c65a598a6907dcf70478517b8d7aa1ab5747d034146e764ba8
F lib/null.cpp 29054e85daa1a2df68d638c5745924906e8479344e057f8b1f8a151b3ced7fd9
F lib/null.h 885bb0030775f0abf6e3ea62975d5e80b14b3774290466b8bc6c0475e15d945b
F lib/options.cpp 0e19d7f530501f79c747c6a60f7d8f4e53fc1f17474da38e50a6794608346c99
F lib/options.h e426a7427be8fd7ece43c1a2a23704388cbff8cac998742d67bd7d3f6a5e9864
F lib/qparms.cpp c3c7ece6a8cf4381813feb977ccd21cf076aec1af0b5056b0b2bbb12c1cfdb40
F lib/qparms.h 79db4335641deba0db8f107584357de812eb34554054572a5a3b0eb3288e7a28
F lib/query.cpp a0d3e3a916f5ae4c4899294be4cbf03c6544017e6465f7481bbe3dd81ca31543
F lib/query.h ff9d4120efd258a4638e2af9a74d7a1539180d137f4304d7a508100b803b3742
F lib/querydef.h a42f3204b27062fd462b4f4edca9f904e89b01310a4683b194ca4720f0994771
F lib/querydef.pl b79a8d4d97fe46bd5aecfc01a3247723a406c5a5ec3f97467b900aee32c2c60b x
F lib/refcounted.h b547dd6a84a3959debe10b4a6c6848e0e85c62f81ab7c817757ca08435ce5f1f
F lib/result.cpp c607b01012068721ef1a9368de745823f161c1c54269d89c45f13bcbaa9edfcd
F lib/result.h 45a3d9569eea39511ffb851e16dc42d2c2e19ccc800d49659cb2511bb77f6cad
F lib/row.cpp 4ba4e766292db1bdcee4900b1af50d2f651bae82513e5d9eb482383333e9d6df
F lib/row.h c5b3593b15455839b8cb834ba35f6191927122400b410896f237aceceb99b286
F lib/scopedconnection.cpp 6df0bc476d007b09774d7dbb40cfaf1fd4c573d74c4a34ef30a3c1a777e4a9e9
F lib/scopedconnection.h 146a49b448e61c0cbc4ef86b11160830b5df42fd1c9e3c0c5f1191199ef734d0
F lib/sql_buffer.cpp be96654c01d929005c17e934a12d1b9f20ae25c4badd86816370f60000c77ecf
F lib/sql_buffer.h 68c0b526af54a2eb3e17b68aeeebde1d525360068992ba28b6620ce5691dedf8
F lib/sql_types.h e121e529fce8e070a476d79e83d5dfa3049bf48718b38e3a68d179df84c86159
F lib/sqlstream.cpp 991164b05a878f4ee3d1baa426d9051e9867ec5d2621515ba57e529a5b75b943
F lib/sqlstream.h a4734317d1215fe89fda7c98db76bfc17219538af03d817d39d777ee24e90d84
F lib/ssqls.h c1c3820e0827939d3df82c8d45bea779fa2b4a56c6d857bdf287eabd3995d9a0
F lib/ssqls.pl 78947795fb61195bb4c168edcad265402148d2371b445b1dfe27bbbeaa827fc7 x
F lib/ssqls2.cpp dc09245b78971a66cc6355a97fe94452069727521b220cd06565b8509394867f
F lib/ssqls2.h aed72d98f892b9ab4794e7a74eb0499a1e8ee81e1be1bf6e8eee3712c751d923
F lib/stadapter.cpp 293aa63a38226de8bf141756f6ef03bace592b3636f2b1b75522b69b2dafa7fe
F lib/stadapter.h c4d6a12f569e7999d121831fa80d3639b7502f640cc9d4562a98eef443f400cb
F lib/stream2string.h 602da8de8b7273ac144bca3e120982754071ec64e43003f512931e206cf5f536
F lib/tcp_connection.cpp e2b1a929088f62d8ad8ab79561356c3d30b0e8a5a0cf4d529231f3669a67b8b7
F lib/tcp_connection.h e1faf059e010075cf7f7ddbe51f2a6fb7558ee2ea5ee7c3da6599d7fa00a3cbb
F lib/tiny_int.h 93e87d50703c4871eb237bf88918ad0a7147c4f4abc7f3475c07fd4b2817825c
F lib/transaction.cpp 6a22f445fde399e3c480ffd5f2f6a355c6e8468ff29ca889986f471a57bdd138
F lib/transaction.h fcfcbfdc2784cd7865da4ecb5599ba2d81a3d8b0d3b20fde3d622fdcd57e5496
F lib/type_info.cpp 49545f109dce70d56c2916d98aef98c18e6b21a33e25e7c8601ff28534747e5e
F lib/type_info.h c5e26d4545acc1f15a95106b47f7d9e1a42ba2f9e3ddb0b8d653c4b9e2b38a1b
F lib/uds_connection.cpp a352c7da19ce1edf8ee57db3ab249af839fb6f7ccd0983146bc25c4087ae2f7e
F lib/uds_connection.h 4f35bc022706e0e03f68a5b5b727c709762af0ed9d674375f3f276e7d3cd5c59
F lib/utility.cpp 63e396efbf46336a08bbb56caf9c1a2642e396f29df22339df77b6c1616214ac
F lib/utility.h b4e321364dd5a98972e8100063cb7bbc83bf2cfbc09fa8f43b093d54dbfe69cf
F lib/vallist.cpp 9ea8d22a4e9c4326e5f5bd6e4dbbc9a5baa114cf4d197d46671fde3a3f945242
F lib/vallist.h cbbae0e30b0185301274d72cbf05d2c4f6ee1b06003c1978a651700cc45171c6
F lib/wnp_connection.cpp de966c60fd69b4d62c6e2cdf8e8741a40297d2d99207cfd2bed2f039b3a40cb2
F lib/wnp_connection.h bccc35d1af3f637f78f1dd400ef873017550ab3a896bedfd17a7614b4998fb24
F mysql++.bkl 90815f6af6101e36661fdbe58810979f8f29161d11b0656d1ddd61a0b4a22dad
F mysql++.ebuild 007ec3580f0562fb5db37f2ce011bf4cc797e9449e1e2b61ebd03afd57e57c51
F mysql++.spec.in ecc51cff6a7758f0c7186fef5be013873bea924507a81567f0195eb038523758
F osver 034cabb5f0517c3b0a3bedcf712289fd6b4b205ee9576940a1440dc85060c230 x
F pretty.pl 011358a7e49ceab10b1bcd5e8484edd2b28e3874723ffa95677b79f74ae7e010 l
F rebake.bat edb44b9acedd5fb9008b2f66a96f3e5dc525128384487a6ce52e9c5fbc19408f
F ssx/Doxyfile.in d1e8bef94b0da6d3da1b1829f76cabedb507ede2940520be30b15280fe91d771
F ssx/genv2.cpp 02dae227776f3eb71eb2ccd4991f5eec91c10c9be039c7ecf0aed9d10bf22100
F ssx/genv2.h 86b0944613f461c68b00703b1ee5cdbc99e773181f8ace99cc274cd1e08c76fa
F ssx/main.cpp db1743722b6f2868b00e95e0dce6a9f39f12aa9b11d28984e415d816ea853078
F ssx/parsev2.cpp 934b8385dd2dd27d9c2b7818f5f19667a0b7725e85d596d441cbba79a97e02ec
F ssx/parsev2.h de6fdfeecab8a96849ad351a32c5f83269bcfb99c88fb3e49cce129962856015
F test/array_index.cpp adbceb7e9e7e403a2a4484e81eefa5d13759e70987850c2e77ac10978256b46c
F test/cpool.cpp be6de03a0a847eea8f730ef35833447d278980c436c76bdf44f1aedcb20ed2d3
F test/datetime.cpp 9047e5ebbe9ace632bc89f529b26357a2fe7ac4d37bab5a60a6e6e241a60d57d
F test/insertpolicy.cpp 5a7114d4d9fe8c261dd3ba0aa919ae41cecbe3984a6609cc37b5611a794284ee
F test/inttypes.cpp c34b5e41c64b48283b0964c472e6c4ab1ecc1a328010e4cb406707a47f770ec6
F test/manip.cpp dceda6b2c16a4008cc5cd34503761b20268b023bc3d3e6626b62dd9538f31742
F test/null_comparison.cpp 75a312a0eccb4e6f31ebb0aa99a30590d6f97cad6df55bd462c09b3a93daec22
F test/null_uniqueness.cpp 2f559c7660e199105942c9e8e5078e9879ac5f6b12f8a58bc15a05a824b49d7c
F test/qssqls.cpp 5473f4fdba4870218fc36ac87d5bdb8e287fcd455260d2d297ebb43da1f2533c
F test/qstream.cpp 18be87d072ad4164261eb1c11039624a611cc057d9425b253afe7008832ad3dd
F test/query_copy.cpp d0d217a8e71dfb8c642678e53d3e069bd24072bdcbc0d4c18eebcbd4b3568816
F test/sqlstream.cpp 11254c5fdb9cfd0402d161770f428bca3f2cb17707d598f55bb39b8854695f8a
F test/ssqls2.cpp f302f79b2eff7e22088182d59f89e3508fbb5e663e670e24d21fe2d9910da0d9
F test/string.cpp ca2fea6f0d7cb9a394b28072764617ba1e50cb00de75ed9e78b2770a1cf1809b
F test/tcp.cpp aca2d45cd823a794cd56785d27ef1ef2e04cd4c5e7ca4a010b10ee08cb7f7042
F test/uds.cpp 31e025a2e6f475df255f3d8b6804b05bba25df96c691d5735208e283f099cb71
F test/wnp.cpp e78010d72bcffaf470d96d4dffb4889550f3c38fd0ab3d992b41e4297f224f92
F tools/tarballs-to-fossil 2d30d1c75564dc022629776a211d925c22e20ae173880026d121bef137c820a6 x
F tools/tb-ignore-glob cf417182914f1e5b978c8d55f226f6d4591eaf4e6112cb8e31cdeae27ec5dc2d
F version.in d74e1616b35e78d414f7b4958f6daac2e2c28d30318c0ffbdefbd2ee4b9b6744


P ec5f1253fcdd465dac5abcbed2b52efda5cc0e852a1ed0a521f373d925e8eed8
R ad9b4312f4413193bd3987a35c930f57
U tangent


Z 6bf0cc2a91fabbfe08131b88ef41800b

Changes to tools/tb-ignore-glob.

1
2


3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
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
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101

*~
*/#*


*.dsp
*.dsw
*.log
*.old
*.svn/*
*.vcproj
abi.xml
acconfig.h
acinclude.m4
aclocal.m4
bk.deps
config.guess
config.h
config.status
config.sub
Configure
configure
config/libtool.m4
config/lt*.m4
devel/*
depcomp
doc/*.pdf
doc/*.tex
doc/CVS/*
doc/html/*
doc/html.sty
doc/Makefile.in
doc/Makefile.org
doc/man-html/*
doc/man-text/*
doc/manual.aux
doc/manual.dvi
doc/manual.ps
doc/manual.ps.gz


doc/manual.toc
doc/refman/html/*
doc/userman/*.txt
doc/userman/html/*

examples/*.bpg
examples/*.bpf
examples/*.bpr
examples/*.dsp
examples/*.dsw
examples/*.vcproj
examples/Makefile.in

html.sty
install.hta
install-sh

lib/Doxyfile
lib/mysql++.h
libtool
ltconfig
ltmain.sh
macros/Makefile.in
Makefile
Makefile.in
man-html/*
man-text/*
manual.aux
manual.dvi
manual.tex
manual.toc
missing
mkinstalldirs
mysql-config
mysql++-config.hh
mysql++-int/*.gif
mysql++-int/gifs.db
mysql++-int/less
mysql++-int/libmysql++.so
mysql++.xcodeproj/*
mysql++.spec
sqlplusint/*.bpg
sqlplusint/*.bpf
sqlplusint/*.bpr
sqlplusint/*.flt
sqlplusint/*.gif
sqlplusint/*.plt
sqlplusint/bad_query.hh
sqlplusint/custom*.hh
sqlplusint/doc-fix.pl
sqlplusint/doc-trim.pl
sqlplusint/doc.tex
sqlplusint/doc.tex.tmpl
sqlplusint/headers
sqlplusint/includes.pl
sqlplusint/gifs.db
sqlplusint/less
sqlplusint/stamp-h2
sqlplusint/stamp-h2.in
sqlplusint/undef_short
ssx/Doxyfile
stamp-h
stamp-h.in
stamp-h1
stamp-h1.in
vc2*/*
version


<
|
>
>
|
|
|
<
|
|
|
<
<
<
<
<
<
<
<
<
<
<
<
|
<
|
<
<
<
<
<
<
<
<
<
<
<
|
>
>
|
<
<
<
>
|
|
<
<
<
<
<
>
|
<
<
>
|
|
|
|
|
|
|
|
|
|
<
<
<
<
|
<
|
<
<
<
<
<
|
<
|
<
<
<
<
<
<
<
<
<
<
<
|
<
<
<
<
<
<
|
<
<
<
<
<
|

>

1
2
3
4
5
6

7
8
9












10

11











12
13
14
15



16
17
18





19
20


21
22
23
24
25
26
27
28
29
30
31




32

33





34

35











36






37





38
39
40

#!/bin/bash
ignores="$(tr '\n' ',' < ../tb-ignore-glob)"
rdir=~/tangentsoft.com/mysql++/releases

set -e
ls $rdir/*.tar.gz | 

        ggrep -Po '\d[\d.]+\d[.a-f]{0,2}' | 
        sed -e 's/\.$//' |
        gsort -t. -k 1,1n -k 2,2n -k 3,3n -k 4,4n |












while read ver

do











    f=$(echo $rdir/*-${ver}.tar.gz)
    echo -e "\n----------------------------------------------------------"
    echo -e "Processing MySQL++ v$ver, $(basename $f)...\n"




    find . -type f -not -name .fslckout -delete
    find . -type d -delete






    if gtar -x --strip-components=1 -f "$f"
    then


        fossil addremove --ignore "$ignores"

        if [ -e ChangeLog ]
        then
            newest=ChangeLog
        else
            newest=$(find . -type f -print0 | xargs -0 ls -t | head -n 2 | tail -1)
        fi
        mtime=$(date -u -r "$newest" +%FT%TZ)
        
        echo "Checking in MySQL++ v$ver, mtime=$mtime..."




        fossil ci \

            --comment "Version $ver" \





            --date-override $mtime \

            --no-warnings \











            --tag "v$ver"






    fi





done

fossil ui

Changes to version.in.





1







2













#!/bin/sh







echo @MYSQLPP_VERSION_MAJOR@.@MYSQLPP_VERSION_MINOR@.@MYSQLPP_VERSION_BUGFIX@









>
>
>
>
|
>
>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
Prerequisite: Install MySQL
~~~~~~~~~~~~~~~~~~~~~~~~~~~
    Before you can build MySQL++, you need to install the
    libmysqlclient-devel package with Cygwin's setup.exe.

	In the past, you had to build MySQL from source, since
	there was no reliable place to get a binary version of the
	client library for Cygwin.  If you must still do this for
	some reason, here's a hint on how to build just the client
	library, since you probably will be running either a native
	Windows version of the server, or have the server installed
	on another machine entirely:

    $ ./configure --prefix=/usr --sysconfdir=/etc --localstatedir=/var \
        --infodir=/usr/share/info --mandir=/usr/share/man \
        --disable-shared --without-{debug,readline,libedit,server}


Building the Library and Example Programs
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    Having done that, Cygwin behaves like any other Unixy system.
	See the instructions in README-Unix.txt.