]> git.saurik.com Git - wxWidgets.git/blob - samples/db/dbtest.cpp
glibc's vswprintf doesn't nul terminate on truncation.
[wxWidgets.git] / samples / db / dbtest.cpp
1 ///////////////////////////////////////////////////////////////////////////////
2 // Name: dbtest.cpp
3 // Purpose: wxWidgets database demo app
4 // Author: George Tasker
5 // Modified by:
6 // Created: 1998
7 // RCS-ID: $Id$
8 // Copyright: (c) 1998 Remstar International, Inc.
9 // Licence: wxWindows licence
10 ///////////////////////////////////////////////////////////////////////////////
11
12 /*
13 * SYNOPSIS START
14
15 This sample program demonstrates the cross-platform ODBC database classes
16 donated by the development team at Remstar International.
17
18 The table this sample is based on is developer contact table, and shows
19 some of the simple uses of the database classes wxDb and wxDbTable.
20
21 * SYNOPSIS END
22 */
23
24 #include "wx/wxprec.h"
25
26 #ifdef __BORLANDC__
27 #pragma hdrstop
28 #endif //__BORLANDC__
29
30 #ifndef WX_PRECOMP
31 #include "wx/wx.h"
32 #endif //WX_PRECOMP
33
34 #if defined(__WXGTK__) || defined(__WXX11__) || defined(__WXMAC__)
35 #include "db.xpm"
36 #endif
37
38 #include <stdio.h> /* Included strictly for reading the text file with the database parameters */
39
40 //#include "wx/db.h" /* Required in the file which will get the data source connection */
41 //#include "wx/dbtable.h" /* Has the wxDbTable object from which all data objects will inherit their data table functionality */
42
43 //extern wxDbList WXDLLEXPORT *PtrBegDbList; /* from db.cpp, used in getting back error results from db connections */
44
45 #if wxUSE_GRID
46 #include "wx/grid.h"
47 #include "wx/generic/gridctrl.h"
48 #include "wx/dbgrid.h"
49
50 #define CHOICEINT
51 #endif
52
53 #include "dbtest.h" /* Header file for this demonstration program */
54 #include "listdb.h" /* Code to support the "Lookup" button on the editor dialog */
55
56 IMPLEMENT_APP(DatabaseDemoApp)
57
58 extern wxChar ListDB_Selection[]; /* Used to return the first column value for the selected line from the listDB routines */
59 extern wxChar ListDB_Selection2[]; /* Used to return the second column value for the selected line from the listDB routines */
60
61 #ifdef wxODBC_BLOB_SUPPORT
62 #include "wx/file.h"
63 #include "wx/mstream.h"
64 #include "wx/image.h"
65 #include "wx/bitmap.h"
66 #include "wx/statbmp.h"
67 #endif
68
69 #if !wxUSE_ODBC
70 #error Sample cannot be compiled unless setup.h has wxUSE_ODBC set to 1
71 #endif
72
73
74 bool DataTypeSupported(wxDb *pDb, SWORD datatype, wxString *nativeDataTypeName)
75 {
76 wxDbSqlTypeInfo sqlTypeInfo;
77
78 bool breakpoint = false;
79
80 *nativeDataTypeName = wxEmptyString;
81 if (pDb->GetDataTypeInfo(datatype, sqlTypeInfo))
82 {
83 *nativeDataTypeName = sqlTypeInfo.TypeName;
84 breakpoint = true;
85 }
86
87 return breakpoint;
88
89 } // GetDataTypesSupported();
90
91
92
93 void CheckSupportForAllDataTypes(wxDb *pDb)
94 {
95 wxString nativeDataTypeName;
96
97 wxLogMessage(wxT("\nThe following datatypes are supported by the\ndatabase you are currently connected to:"));
98 #ifdef SQL_C_BINARY
99 if (DataTypeSupported(pDb,SQL_C_BINARY, &nativeDataTypeName))
100 {
101 nativeDataTypeName = wxT("SQL_C_BINARY (") + nativeDataTypeName;
102 nativeDataTypeName += wxT(")\n");
103 wxLogMessage(nativeDataTypeName);
104 }
105 #endif
106 #ifdef SQL_C_BIT
107 if (DataTypeSupported(pDb,SQL_C_BIT, &nativeDataTypeName))
108 {
109 nativeDataTypeName = wxT("SQL_C_BIT (") + nativeDataTypeName;
110 nativeDataTypeName += wxT(")\n");
111 wxLogMessage(nativeDataTypeName);
112 }
113 #endif
114 #ifdef SQL_C_BOOKMARK
115 if (DataTypeSupported(pDb,SQL_C_BOOKMARK, &nativeDataTypeName))
116 {
117 nativeDataTypeName = wxT("SQL_C_BOOKMARK (") + nativeDataTypeName;
118 nativeDataTypeName += wxT(")\n");
119 wxLogMessage(nativeDataTypeName);
120 }
121 #endif
122 #ifdef SQL_C_CHAR
123 if (DataTypeSupported(pDb,SQL_C_CHAR, &nativeDataTypeName))
124 {
125 nativeDataTypeName = wxT("SQL_C_CHAR (") + nativeDataTypeName;
126 nativeDataTypeName += wxT(")\n");
127 wxLogMessage(nativeDataTypeName);
128 }
129 #endif
130 #ifdef SQL_C_DATE
131 if (DataTypeSupported(pDb,SQL_C_DATE, &nativeDataTypeName))
132 {
133 nativeDataTypeName = wxT("SQL_C_DATE (") + nativeDataTypeName;
134 nativeDataTypeName += wxT(")\n");
135 wxLogMessage(nativeDataTypeName);
136 }
137 #endif
138 #ifdef SQL_C_DEFAULT
139 if (DataTypeSupported(pDb,SQL_C_DEFAULT, &nativeDataTypeName))
140 {
141 nativeDataTypeName = wxT("SQL_C_DEFAULT (") + nativeDataTypeName;
142 nativeDataTypeName += wxT(")\n");
143 wxLogMessage(nativeDataTypeName);
144 }
145 #endif
146 #ifdef SQL_C_DOUBLE
147 if (DataTypeSupported(pDb,SQL_C_DOUBLE, &nativeDataTypeName))
148 {
149 nativeDataTypeName = wxT("SQL_C_DOUBLE (") + nativeDataTypeName;
150 nativeDataTypeName += wxT(")\n");
151 wxLogMessage(nativeDataTypeName);
152 }
153 #endif
154 #ifdef SQL_C_FLOAT
155 if (DataTypeSupported(pDb,SQL_C_FLOAT, &nativeDataTypeName))
156 {
157 nativeDataTypeName = wxT("SQL_C_FLOAT (") + nativeDataTypeName;
158 nativeDataTypeName += wxT(")\n");
159 wxLogMessage(nativeDataTypeName);
160 }
161 #endif
162 #ifdef SQL_C_GUID
163 if (DataTypeSupported(pDb,SQL_C_GUID, &nativeDataTypeName))
164 {
165 nativeDataTypeName = wxT("SQL_C_GUID (") + nativeDataTypeName;
166 nativeDataTypeName += wxT(")\n");
167 wxLogMessage(nativeDataTypeName);
168 }
169 #endif
170 #ifdef SQL_C_INTERVAL_DAY
171 if (DataTypeSupported(pDb,SQL_C_INTERVAL_DAY, &nativeDataTypeName))
172 {
173 nativeDataTypeName = wxT("SQL_C_INTERVAL_DAY (") + nativeDataTypeName;
174 nativeDataTypeName += wxT(")\n");
175 wxLogMessage(nativeDataTypeName);
176 }
177 #endif
178 #ifdef SQL_C_INTERVAL_DAY_TO_HOUR
179 if (DataTypeSupported(pDb,SQL_C_INTERVAL_DAY_TO_HOUR, &nativeDataTypeName))
180 {
181 nativeDataTypeName = wxT("SQL_C_INTERVAL_DAY_TO_HOUR (") + nativeDataTypeName;
182 nativeDataTypeName += wxT(")\n");
183 wxLogMessage(nativeDataTypeName);
184 }
185 #endif
186 #ifdef SQL_C_INTERVAL_DAY_TO_MINUTE
187 if (DataTypeSupported(pDb,SQL_C_INTERVAL_DAY_TO_MINUTE, &nativeDataTypeName))
188 {
189 nativeDataTypeName = wxT("SQL_C_INTERVAL_DAY_TO_MINUTE (") + nativeDataTypeName;
190 nativeDataTypeName += wxT(")\n");
191 wxLogMessage(nativeDataTypeName);
192 }
193 #endif
194 #ifdef SQL_C_INTERVAL_DAY_TO_SECOND
195 if (DataTypeSupported(pDb,SQL_C_INTERVAL_DAY_TO_SECOND, &nativeDataTypeName))
196 {
197 nativeDataTypeName = wxT("SQL_C_INTERVAL_DAY_TO_SECOND (") + nativeDataTypeName;
198 nativeDataTypeName += wxT(")\n");
199 wxLogMessage(nativeDataTypeName);
200 }
201 #endif
202 #ifdef SQL_C_INTERVAL_HOUR
203 if (DataTypeSupported(pDb,SQL_C_INTERVAL_HOUR, &nativeDataTypeName))
204 {
205 nativeDataTypeName = wxT("SQL_C_INTERVAL_HOUR (") + nativeDataTypeName;
206 nativeDataTypeName += wxT(")\n");
207 wxLogMessage(nativeDataTypeName);
208 }
209 #endif
210 #ifdef SQL_C_INTERVAL_HOUR_TO_MINUTE
211 if (DataTypeSupported(pDb,SQL_C_INTERVAL_HOUR_TO_MINUTE, &nativeDataTypeName))
212 {
213 nativeDataTypeName = wxT("SQL_C_INTERVAL_HOUR_TO_MINUTE (") + nativeDataTypeName;
214 nativeDataTypeName += wxT(")\n");
215 wxLogMessage(nativeDataTypeName);
216 }
217 #endif
218 #ifdef SQL_C_INTERVAL_HOUR_TO_SECOND
219 if (DataTypeSupported(pDb,SQL_C_INTERVAL_HOUR_TO_SECOND, &nativeDataTypeName))
220 {
221 nativeDataTypeName = wxT("SQL_C_INTERVAL_HOUR_TO_SECOND (") + nativeDataTypeName;
222 nativeDataTypeName += wxT(")\n");
223 wxLogMessage(nativeDataTypeName);
224 }
225 #endif
226 #ifdef SQL_C_INTERVAL_MINUTE
227 if (DataTypeSupported(pDb,SQL_C_INTERVAL_MINUTE, &nativeDataTypeName))
228 {
229 nativeDataTypeName = wxT("SQL_C_INTERVAL_MINUTE (") + nativeDataTypeName;
230 nativeDataTypeName += wxT(")\n");
231 wxLogMessage(nativeDataTypeName);
232 }
233 #endif
234 #ifdef SQL_C_INTERVAL_MINUTE_TO_SECOND
235 if (DataTypeSupported(pDb,SQL_C_INTERVAL_MINUTE_TO_SECOND, &nativeDataTypeName))
236 {
237 nativeDataTypeName = wxT("SQL_C_INTERVAL_MINUTE_TO_SECOND (") + nativeDataTypeName;
238 nativeDataTypeName += wxT(")\n");
239 wxLogMessage(nativeDataTypeName);
240 }
241 #endif
242 #ifdef SQL_C_INTERVAL_MONTH
243 if (DataTypeSupported(pDb,SQL_C_INTERVAL_MONTH, &nativeDataTypeName))
244 {
245 nativeDataTypeName = wxT("SQL_C_INTERVAL_MONTH (") + nativeDataTypeName;
246 nativeDataTypeName += wxT(")\n");
247 wxLogMessage(nativeDataTypeName);
248 }
249 #endif
250 #ifdef SQL_C_INTERVAL_SECOND
251 if (DataTypeSupported(pDb,SQL_C_INTERVAL_SECOND, &nativeDataTypeName))
252 {
253 nativeDataTypeName = wxT("SQL_C_INTERVAL_SECOND (") + nativeDataTypeName;
254 nativeDataTypeName += wxT(")\n");
255 wxLogMessage(nativeDataTypeName);
256 }
257 #endif
258 #ifdef SQL_C_INTERVAL_YEAR
259 if (DataTypeSupported(pDb,SQL_C_INTERVAL_YEAR, &nativeDataTypeName))
260 {
261 nativeDataTypeName = wxT("SQL_C_INTERVAL_YEAR (") + nativeDataTypeName;
262 nativeDataTypeName += wxT(")\n");
263 wxLogMessage(nativeDataTypeName);
264 }
265 #endif
266 #ifdef SQL_C_INTERVAL_YEAR_TO_MONTH
267 if (DataTypeSupported(pDb,SQL_C_INTERVAL_YEAR_TO_MONTH, &nativeDataTypeName))
268 {
269 nativeDataTypeName = wxT("SQL_C_INTERVAL_YEAR_TO_MONTH (") + nativeDataTypeName;
270 nativeDataTypeName += wxT(")\n");
271 wxLogMessage(nativeDataTypeName);
272 }
273 #endif
274 #ifdef SQL_C_LONG
275 if (DataTypeSupported(pDb,SQL_C_LONG, &nativeDataTypeName))
276 {
277 nativeDataTypeName = wxT("SQL_C_LONG (") + nativeDataTypeName;
278 nativeDataTypeName += wxT(")\n");
279 wxLogMessage(nativeDataTypeName);
280 }
281 #endif
282 #ifdef SQL_C_NUMERIC
283 if (DataTypeSupported(pDb,SQL_C_NUMERIC, &nativeDataTypeName))
284 {
285 nativeDataTypeName = wxT("SQL_C_NUMERIC (") + nativeDataTypeName;
286 nativeDataTypeName += wxT(")\n");
287 wxLogMessage(nativeDataTypeName);
288 }
289 #endif
290 #ifdef SQL_C_SBIGINT
291 if (DataTypeSupported(pDb,SQL_C_SBIGINT, &nativeDataTypeName))
292 {
293 nativeDataTypeName = wxT("SQL_C_SBIGINT (") + nativeDataTypeName;
294 nativeDataTypeName += wxT(")\n");
295 wxLogMessage(nativeDataTypeName);
296 }
297 #endif
298 #ifdef SQL_C_SHORT
299 if (DataTypeSupported(pDb,SQL_C_SHORT, &nativeDataTypeName))
300 {
301 nativeDataTypeName = wxT("SQL_C_SHORT (") + nativeDataTypeName;
302 nativeDataTypeName += wxT(")\n");
303 wxLogMessage(nativeDataTypeName);
304 }
305 #endif
306 #ifdef SQL_C_SLONG
307 if (DataTypeSupported(pDb,SQL_C_SLONG, &nativeDataTypeName))
308 {
309 nativeDataTypeName = wxT("SQL_C_SLONG (") + nativeDataTypeName;
310 nativeDataTypeName += wxT(")\n");
311 wxLogMessage(nativeDataTypeName);
312 }
313 #endif
314 #ifdef SQL_C_SSHORT
315 if (DataTypeSupported(pDb,SQL_C_SSHORT, &nativeDataTypeName))
316 {
317 nativeDataTypeName = wxT("SQL_C_SSHORT (") + nativeDataTypeName;
318 nativeDataTypeName += wxT(")\n");
319 wxLogMessage(nativeDataTypeName);
320 }
321 #endif
322 #ifdef SQL_C_STINYINT
323 if (DataTypeSupported(pDb,SQL_C_STINYINT, &nativeDataTypeName))
324 {
325 nativeDataTypeName = wxT("SQL_C_STINYINT (") + nativeDataTypeName;
326 nativeDataTypeName += wxT(")\n");
327 wxLogMessage(nativeDataTypeName);
328 }
329 #endif
330 #ifdef SQL_C_TIME
331 if (DataTypeSupported(pDb,SQL_C_TIME, &nativeDataTypeName))
332 {
333 nativeDataTypeName = wxT("SQL_C_TIME (") + nativeDataTypeName;
334 nativeDataTypeName += wxT(")\n");
335 wxLogMessage(nativeDataTypeName);
336 }
337 #endif
338 #ifdef SQL_C_TIMESTAMP
339 if (DataTypeSupported(pDb,SQL_C_TIMESTAMP, &nativeDataTypeName))
340 {
341 nativeDataTypeName = wxT("SQL_C_TIMESTAMP (") + nativeDataTypeName;
342 nativeDataTypeName += wxT(")\n");
343 wxLogMessage(nativeDataTypeName);
344 }
345 #endif
346 #ifdef SQL_C_TINYINT
347 if (DataTypeSupported(pDb,SQL_C_TINYINT, &nativeDataTypeName))
348 {
349 nativeDataTypeName = wxT("SQL_C_TINYINT (") + nativeDataTypeName;
350 nativeDataTypeName += wxT(")\n");
351 wxLogMessage(nativeDataTypeName);
352 }
353 #endif
354 #ifdef SQL_C_TYPE_DATE
355 if (DataTypeSupported(pDb,SQL_C_TYPE_DATE, &nativeDataTypeName))
356 {
357 nativeDataTypeName = wxT("SQL_C_TYPE_DATE (") + nativeDataTypeName;
358 nativeDataTypeName += wxT(")\n");
359 wxLogMessage(nativeDataTypeName);
360 }
361 #endif
362 #ifdef SQL_C_TYPE_TIME
363 if (DataTypeSupported(pDb,SQL_C_TYPE_TIME, &nativeDataTypeName))
364 {
365 nativeDataTypeName = wxT("SQL_C_TYPE_TIME (") + nativeDataTypeName;
366 nativeDataTypeName += wxT(")\n");
367 wxLogMessage(nativeDataTypeName);
368 }
369 #endif
370 #ifdef SQL_C_TYPE_TIMESTAMP
371 if (DataTypeSupported(pDb,SQL_C_TYPE_TIMESTAMP, &nativeDataTypeName))
372 {
373 nativeDataTypeName = wxT("SQL_C_TYPE_TIMESTAMP (") + nativeDataTypeName;
374 nativeDataTypeName += wxT(")\n");
375 wxLogMessage(nativeDataTypeName);
376 }
377 #endif
378 #ifdef SQL_C_UBIGINT
379 if (DataTypeSupported(pDb,SQL_C_UBIGINT, &nativeDataTypeName))
380 {
381 nativeDataTypeName = wxT("SQL_C_UBIGINT (") + nativeDataTypeName;
382 nativeDataTypeName += wxT(")\n");
383 wxLogMessage(nativeDataTypeName);
384 }
385 #endif
386 #ifdef SQL_C_ULONG
387 if (DataTypeSupported(pDb,SQL_C_ULONG, &nativeDataTypeName))
388 {
389 nativeDataTypeName = wxT("SQL_C_ULONG (") + nativeDataTypeName;
390 nativeDataTypeName += wxT(")\n");
391 wxLogMessage(nativeDataTypeName);
392 }
393 #endif
394 #ifdef SQL_C_USHORT
395 if (DataTypeSupported(pDb,SQL_C_USHORT, &nativeDataTypeName))
396 {
397 nativeDataTypeName = wxT("SQL_C_USHORT (") + nativeDataTypeName;
398 nativeDataTypeName += wxT(")\n");
399 wxLogMessage(nativeDataTypeName);
400 }
401 #endif
402 #ifdef SQL_C_UTINYINT
403 if (DataTypeSupported(pDb,SQL_C_UTINYINT, &nativeDataTypeName))
404 {
405 nativeDataTypeName = wxT("SQL_C_UTINYINT (") + nativeDataTypeName;
406 nativeDataTypeName += wxT(")\n");
407 wxLogMessage(nativeDataTypeName);
408 }
409 #endif
410 #ifdef SQL_C_VARBOOKMARK
411 if (DataTypeSupported(pDb,SQL_C_VARBOOKMARK, &nativeDataTypeName))
412 {
413 nativeDataTypeName = wxT("SQL_C_VARBOOKMARK (") + nativeDataTypeName;
414 nativeDataTypeName += wxT(")\n");
415 wxLogMessage(nativeDataTypeName);
416 }
417 #endif
418 #ifdef SQL_C_WXCHAR
419 if (DataTypeSupported(pDb,SQL_C_WXCHAR, &nativeDataTypeName))
420 {
421 nativeDataTypeName = wxT("SQL_C_WXCHAR (") + nativeDataTypeName;
422 nativeDataTypeName += wxT(")\n");
423 wxLogMessage(nativeDataTypeName);
424 }
425 #endif
426
427 // Extended SQL types
428 #ifdef SQL_DATE
429 if (DataTypeSupported(pDb,SQL_DATE, &nativeDataTypeName))
430 {
431 nativeDataTypeName = wxT("SQL_DATE (") + nativeDataTypeName;
432 nativeDataTypeName += wxT(")\n");
433 wxLogMessage(nativeDataTypeName);
434 }
435 #endif
436 #ifdef SQL_INTERVAL
437 if (DataTypeSupported(pDb,SQL_INTERVAL, &nativeDataTypeName))
438 {
439 nativeDataTypeName = wxT("SQL_INTERVAL (") + nativeDataTypeName;
440 nativeDataTypeName += wxT(")\n");
441 wxLogMessage(nativeDataTypeName);
442 }
443 #endif
444 #ifdef SQL_TIME
445 if (DataTypeSupported(pDb,SQL_TIME, &nativeDataTypeName))
446 {
447 nativeDataTypeName = wxT("SQL_TIME (") + nativeDataTypeName;
448 nativeDataTypeName += wxT(")\n");
449 wxLogMessage(nativeDataTypeName);
450 }
451 #endif
452 #ifdef SQL_TIMESTAMP
453 if (DataTypeSupported(pDb,SQL_TIMESTAMP, &nativeDataTypeName))
454 {
455 nativeDataTypeName = wxT("SQL_TIMESTAMP (") + nativeDataTypeName;
456 nativeDataTypeName += wxT(")\n");
457 wxLogMessage(nativeDataTypeName);
458 }
459 #endif
460 #ifdef SQL_LONGVARCHAR
461 if (DataTypeSupported(pDb,SQL_LONGVARCHAR, &nativeDataTypeName))
462 {
463 nativeDataTypeName = wxT("SQL_LONGVARCHAR (") + nativeDataTypeName;
464 nativeDataTypeName += wxT(")\n");
465 wxLogMessage(nativeDataTypeName);
466 }
467 #endif
468 #ifdef SQL_BINARY
469 if (DataTypeSupported(pDb,SQL_BINARY, &nativeDataTypeName))
470 {
471 nativeDataTypeName = wxT("SQL_BINARY (") + nativeDataTypeName;
472 nativeDataTypeName += wxT(")\n");
473 wxLogMessage(nativeDataTypeName);
474 }
475 #endif
476 #ifdef SQL_VARBINARY
477 if (DataTypeSupported(pDb,SQL_VARBINARY, &nativeDataTypeName))
478 {
479 nativeDataTypeName = wxT("SQL_VARBINARY (") + nativeDataTypeName;
480 nativeDataTypeName += wxT(")\n");
481 wxLogMessage(nativeDataTypeName);
482 }
483 #endif
484 #ifdef SQL_LONGVARBINARY
485 if (DataTypeSupported(pDb,SQL_LONGVARBINARY, &nativeDataTypeName))
486 {
487 nativeDataTypeName = wxT("SQL_LOGVARBINARY (") + nativeDataTypeName;
488 nativeDataTypeName += wxT(")\n");
489 wxLogMessage(nativeDataTypeName);
490 }
491 #endif
492 #ifdef SQL_BIGINT
493 if (DataTypeSupported(pDb,SQL_BIGINT, &nativeDataTypeName))
494 {
495 nativeDataTypeName = wxT("SQL_BIGINT (") + nativeDataTypeName;
496 nativeDataTypeName += wxT(")\n");
497 wxLogMessage(nativeDataTypeName);
498 }
499 #endif
500 #ifdef SQL_TINYINT
501 if (DataTypeSupported(pDb,SQL_TINYINT, &nativeDataTypeName))
502 {
503 nativeDataTypeName = wxT("SQL_TINYINT (") + nativeDataTypeName;
504 nativeDataTypeName += wxT(")\n");
505 wxLogMessage(nativeDataTypeName);
506 }
507 #endif
508 #ifdef SQL_BIT
509 if (DataTypeSupported(pDb,SQL_BIT, &nativeDataTypeName))
510 {
511 nativeDataTypeName = wxT("SQL_BIT (") + nativeDataTypeName;
512 nativeDataTypeName += wxT(")\n");
513 wxLogMessage(nativeDataTypeName);
514 }
515 #endif
516 #ifdef SQL_GUID
517 if (DataTypeSupported(pDb,SQL_GUID, &nativeDataTypeName))
518 {
519 nativeDataTypeName = wxT("SQL_GUID (") + nativeDataTypeName;
520 nativeDataTypeName += wxT(")\n");
521 wxLogMessage(nativeDataTypeName);
522 }
523 #endif
524
525 #ifdef SQL_CHAR
526 if (DataTypeSupported(pDb,SQL_CHAR, &nativeDataTypeName))
527 {
528 nativeDataTypeName = wxT("SQL_CHAR (") + nativeDataTypeName;
529 nativeDataTypeName += wxT(")\n");
530 wxLogMessage(nativeDataTypeName);
531 }
532 #endif
533 #ifdef SQL_INTEGER
534 if (DataTypeSupported(pDb,SQL_INTEGER, &nativeDataTypeName))
535 {
536 nativeDataTypeName = wxT("SQL_INTEGER (") + nativeDataTypeName;
537 nativeDataTypeName += wxT(")\n");
538 wxLogMessage(nativeDataTypeName);
539 }
540 #endif
541 #ifdef SQL_SMALLINT
542 if (DataTypeSupported(pDb,SQL_SMALLINT, &nativeDataTypeName))
543 {
544 nativeDataTypeName = wxT("SQL_SAMLLINT (") + nativeDataTypeName;
545 nativeDataTypeName += wxT(")\n");
546 wxLogMessage(nativeDataTypeName);
547 }
548 #endif
549 #ifdef SQL_REAL
550 if (DataTypeSupported(pDb,SQL_REAL, &nativeDataTypeName))
551 {
552 nativeDataTypeName = wxT("SQL_REAL (") + nativeDataTypeName;
553 nativeDataTypeName += wxT(")\n");
554 wxLogMessage(nativeDataTypeName);
555 }
556 #endif
557 #ifdef SQL_DOUBLE
558 if (DataTypeSupported(pDb,SQL_DOUBLE, &nativeDataTypeName))
559 {
560 nativeDataTypeName = wxT("SQL_DOUBLE (") + nativeDataTypeName;
561 nativeDataTypeName += wxT(")\n");
562 wxLogMessage(nativeDataTypeName);
563 }
564 #endif
565 #ifdef SQL_NUMERIC
566 if (DataTypeSupported(pDb,SQL_NUMERIC, &nativeDataTypeName))
567 {
568 nativeDataTypeName = wxT("SQL_NUMERIC (") + nativeDataTypeName;
569 nativeDataTypeName += wxT(")\n");
570 wxLogMessage(nativeDataTypeName);
571 }
572 #endif
573 #ifdef SQL_DATE
574 if (DataTypeSupported(pDb,SQL_DATE, &nativeDataTypeName))
575 {
576 nativeDataTypeName = wxT("SQL_DATE (") + nativeDataTypeName;
577 nativeDataTypeName += wxT(")\n");
578 wxLogMessage(nativeDataTypeName);
579 }
580 #endif
581 #ifdef SQL_TIME
582 if (DataTypeSupported(pDb,SQL_TIME, &nativeDataTypeName))
583 {
584 nativeDataTypeName = wxT("SQL_TIME (") + nativeDataTypeName;
585 nativeDataTypeName += wxT(")\n");
586 wxLogMessage(nativeDataTypeName);
587 }
588 #endif
589 #ifdef SQL_TIMESTAMP
590 if (DataTypeSupported(pDb,SQL_TIMESTAMP, &nativeDataTypeName))
591 {
592 nativeDataTypeName = wxT("SQL_TIMESTAMP (") + nativeDataTypeName;
593 nativeDataTypeName += wxT(")\n");
594 wxLogMessage(nativeDataTypeName);
595 }
596 #endif
597 #ifdef SQL_VARCHAR
598 if (DataTypeSupported(pDb,SQL_VARCHAR, &nativeDataTypeName))
599 {
600 nativeDataTypeName = wxT("SQL_VARCHAR (") + nativeDataTypeName;
601 nativeDataTypeName += wxT(")\n");
602 wxLogMessage(nativeDataTypeName);
603 }
604 #endif
605
606 // UNICODE
607 #ifdef SQL_C_TCHAR
608 if (DataTypeSupported(pDb,SQL_C_TCHAR, &nativeDataTypeName))
609 {
610 nativeDataTypeName = wxT("SQL_C_TCHAR (") + nativeDataTypeName;
611 nativeDataTypeName += wxT(")\n");
612 wxLogMessage(nativeDataTypeName);
613 }
614 #endif
615 #ifdef SQL_WVARCHAR
616 if (DataTypeSupported(pDb,SQL_WVARCHAR, &nativeDataTypeName))
617 {
618 nativeDataTypeName = wxT("SQL_WVARCHAR (") + nativeDataTypeName;
619 nativeDataTypeName += wxT(")\n");
620 wxLogMessage(nativeDataTypeName);
621 }
622 #endif
623 #ifdef SQL_WCHAR
624 if (DataTypeSupported(pDb,SQL_WCHAR, &nativeDataTypeName))
625 {
626 nativeDataTypeName = wxT("SQL_WCHAR (") + nativeDataTypeName;
627 nativeDataTypeName += wxT(")\n");
628 wxLogMessage(nativeDataTypeName);
629 }
630 #endif
631
632 wxLogMessage(wxT("Done\n"));
633 } // CheckSupportForAllDataTypes()
634
635
636 bool DatabaseDemoApp::OnInit()
637 {
638 DbConnectInf = NULL;
639 Contact = NULL;
640
641 // Create the main frame window
642 DemoFrame = new DatabaseDemoFrame(NULL, wxT("wxWidgets Database Demo"), wxPoint(50, 50), wxSize(537, 530));
643
644 // Give it an icon
645 DemoFrame->SetIcon(wxICON(db));
646
647 // Make a menubar
648 wxMenu *file_menu = new wxMenu;
649 file_menu->Append(FILE_CREATE_ID, wxT("&Create CONTACT table"));
650 file_menu->Append(FILE_RECREATE_TABLE, wxT("&Recreate CONTACT table"));
651 file_menu->Append(FILE_RECREATE_INDEXES, wxT("&Recreate CONTACT indexes"));
652 #if wxUSE_GRID
653 file_menu->Append(FILE_DBGRID_TABLE, wxT("&Open DB Grid example"));
654 #endif
655 file_menu->Append(FILE_EXIT, wxT("E&xit"));
656
657 wxMenu *edit_menu = new wxMenu;
658 edit_menu->Append(EDIT_PARAMETERS, wxT("&Parameters..."));
659
660 wxMenu *help_menu = new wxMenu;
661 help_menu->Append(HELP_ABOUT, wxT("&About"));
662
663 wxMenuBar *menu_bar = new wxMenuBar;
664 menu_bar->Append(file_menu, wxT("&File"));
665 menu_bar->Append(edit_menu, wxT("&Edit"));
666 menu_bar->Append(help_menu, wxT("&Help"));
667 DemoFrame->SetMenuBar(menu_bar);
668
669 params.ODBCSource[0] = 0;
670 params.UserName[0] = 0;
671 params.Password[0] = 0;
672 params.DirPath[0] = 0;
673
674 #ifdef wxODBC_BLOB_SUPPORT
675 wxInitAllImageHandlers();
676 wxImage::InitStandardHandlers();
677 wxBitmap::InitStandardHandlers();
678 #endif
679
680 // Show the frame
681 DemoFrame->Show(true);
682
683 // Passing NULL for the SQL environment handle causes
684 // the wxDbConnectInf constructor to obtain a handle
685 // for you.
686 //
687 // WARNING: Be certain that you do not free this handle
688 // directly with SQLFreeEnv(). Use either the
689 // method ::FreeHenv() or delete the DbConnectInf.
690 DbConnectInf = new wxDbConnectInf(NULL, params.ODBCSource, params.UserName,
691 params.Password, params.DirPath);
692
693 if (!DbConnectInf || !DbConnectInf->GetHenv())
694 {
695 wxMessageBox(wxT("Unable to define data source connection info."), wxT("DB CONNECTION ERROR..."),wxOK | wxICON_EXCLAMATION);
696 wxDELETE(DbConnectInf);
697 }
698
699 if (!ReadParamFile(params))
700 DemoFrame->BuildParameterDialog(NULL);
701
702 if (!wxStrlen(params.ODBCSource))
703 {
704 wxDELETE(DbConnectInf);
705 return(false);
706 }
707
708 DbConnectInf->SetDsn(params.ODBCSource);
709 DbConnectInf->SetUserID(params.UserName);
710 DbConnectInf->SetPassword(params.Password);
711 DbConnectInf->SetDefaultDir(params.DirPath);
712
713 READONLY_DB = wxDbGetConnection(DbConnectInf);
714 if (READONLY_DB == 0)
715 {
716 wxMessageBox(wxT("Unable to connect to the data source.\n\nCheck the name of your data source to verify it has been correctly entered/spelled.\n\nWith some databases, the user name and password must\nbe created with full rights to the CONTACT table prior to making a connection\n(using tools provided by the database manufacturer)"), wxT("DB CONNECTION ERROR..."),wxOK | wxICON_EXCLAMATION);
717 DemoFrame->BuildParameterDialog(NULL);
718 wxDELETE(DbConnectInf);
719 wxMessageBox(wxT("Now exiting program.\n\nRestart program to try any new settings."),wxT("Notice..."),wxOK | wxICON_INFORMATION);
720 return(false);
721 }
722
723 DemoFrame->BuildEditorDialog();
724
725 // Show the frame
726 DemoFrame->Refresh();
727
728 return true;
729 } // DatabaseDemoApp::OnInit()
730
731
732 /*
733 * Remove CR or CR/LF from a character string.
734 */
735 wxChar* wxRemoveLineTerminator(wxChar* aString)
736 {
737 int len = wxStrlen(aString);
738 while (len > 0 && (aString[len-1] == wxT('\r') || aString[len-1] == wxT('\n'))) {
739 aString[len-1] = wxT('\0');
740 len--;
741 }
742 return aString;
743 }
744
745
746 bool DatabaseDemoApp::ReadParamFile(Cparameters &params)
747 {
748 FILE *paramFile;
749 if ((paramFile = wxFopen(PARAM_FILENAME, wxT("r"))) == NULL)
750 {
751 wxString tStr;
752 tStr.Printf(wxT("Unable to open the parameter file '%s' for reading.\n\nYou must specify the data source, user name, and\npassword that will be used and save those settings."),PARAM_FILENAME.c_str());
753 wxMessageBox(tStr,wxT("File I/O Error..."),wxOK | wxICON_EXCLAMATION);
754
755 return false;
756 }
757
758 wxChar buffer[1000+1];
759 wxFgets(buffer, sizeof(params.ODBCSource), paramFile);
760 wxRemoveLineTerminator(buffer);
761 wxStrcpy(params.ODBCSource,buffer);
762
763 wxFgets(buffer, sizeof(params.UserName), paramFile);
764 wxRemoveLineTerminator(buffer);
765 wxStrcpy(params.UserName,buffer);
766
767 wxFgets(buffer, sizeof(params.Password), paramFile);
768 wxRemoveLineTerminator(buffer);
769 wxStrcpy(params.Password,buffer);
770
771 wxFgets(buffer, sizeof(params.DirPath), paramFile);
772 wxRemoveLineTerminator(buffer);
773 wxStrcpy(params.DirPath,buffer);
774
775 fclose(paramFile);
776
777 return true;
778 } // DatabaseDemoApp::ReadParamFile()
779
780
781 bool DatabaseDemoApp::WriteParamFile(Cparameters &WXUNUSED(params))
782 {
783 FILE *paramFile;
784 if ((paramFile = wxFopen(PARAM_FILENAME, wxT("wt"))) == NULL)
785 {
786 wxString tStr;
787 tStr.Printf(wxT("Unable to write/overwrite '%s'."),PARAM_FILENAME.c_str());
788 wxMessageBox(tStr,wxT("File I/O Error..."),wxOK | wxICON_EXCLAMATION);
789 return false;
790 }
791
792 wxFputs(wxGetApp().params.ODBCSource, paramFile);
793 wxFputc(wxT('\n'), paramFile);
794 wxFputs(wxGetApp().params.UserName, paramFile);
795 wxFputc(wxT('\n'), paramFile);
796 wxFputs(wxGetApp().params.Password, paramFile);
797 wxFputc(wxT('\n'), paramFile);
798 wxFputs(wxGetApp().params.DirPath, paramFile);
799 wxFputc(wxT('\n'), paramFile);
800 fclose(paramFile);
801
802 return true;
803 } // DatabaseDemoApp::WriteParamFile()
804
805
806 void DatabaseDemoApp::CreateDataTable(bool recreate)
807 {
808 bool Ok = true;
809 if (recreate)
810 Ok = (wxMessageBox(wxT("Any data currently residing in the table will be erased.\n\nAre you sure?"),wxT("Confirm"),wxYES_NO|wxICON_QUESTION) == wxYES);
811
812 if (!Ok)
813 return;
814
815 wxBeginBusyCursor();
816
817 bool success = true;
818
819 Contact->GetDb()->RollbackTrans(); // Make sure the current cursor is in a known/stable state
820
821 if (!Contact->CreateTable(recreate))
822 {
823 wxEndBusyCursor();
824 wxString tStr;
825 tStr = wxT("Error creating CONTACTS table.\nTable was not created.\n\n");
826 wxMessageBox(wxDbLogExtendedErrorMsg(tStr.c_str(),Contact->GetDb(),__TFILE__,__LINE__),
827 wxT("ODBC Error..."),wxOK | wxICON_EXCLAMATION);
828
829 success = false;
830 }
831 else
832 {
833 if (!Contact->CreateIndexes(recreate))
834 {
835 wxEndBusyCursor();
836 wxString tStr;
837 tStr = wxT("Error creating CONTACTS indexes.\nIndexes will be unavailable.\n\n");
838 wxMessageBox(wxDbLogExtendedErrorMsg(tStr.c_str(),Contact->GetDb(),__TFILE__,__LINE__),
839 wxT("ODBC Error..."),wxOK | wxICON_EXCLAMATION);
840
841 success = false;
842 }
843 }
844 while (wxIsBusy())
845 wxEndBusyCursor();
846
847 if (success)
848 wxMessageBox(wxT("Table and index(es) were successfully created."),wxT("Notice..."),wxOK | wxICON_INFORMATION);
849 } // DatabaseDemoApp::CreateDataTable()
850
851
852 BEGIN_EVENT_TABLE(DatabaseDemoFrame, wxFrame)
853 EVT_MENU(FILE_CREATE_ID, DatabaseDemoFrame::OnCreate)
854 EVT_MENU(FILE_RECREATE_TABLE, DatabaseDemoFrame::OnRecreateTable)
855 EVT_MENU(FILE_RECREATE_INDEXES, DatabaseDemoFrame::OnRecreateIndexes)
856 #if wxUSE_GRID
857 EVT_MENU(FILE_DBGRID_TABLE, DatabaseDemoFrame::OnDbGridTable)
858 #endif
859 EVT_MENU(FILE_EXIT, DatabaseDemoFrame::OnExit)
860 EVT_MENU(EDIT_PARAMETERS, DatabaseDemoFrame::OnEditParameters)
861 EVT_MENU(HELP_ABOUT, DatabaseDemoFrame::OnAbout)
862 EVT_CLOSE(DatabaseDemoFrame::OnCloseWindow)
863 END_EVENT_TABLE()
864
865
866 // DatabaseDemoFrame constructor
867 DatabaseDemoFrame::DatabaseDemoFrame(wxFrame *frame, const wxString& title,
868 const wxPoint& pos, const wxSize& size):
869 wxFrame(frame, wxID_ANY, title, pos, size)
870 {
871 // Put any code in necessary for initializing the main frame here
872 pEditorDlg = NULL;
873 pParamDlg = NULL;
874
875 #if wxUSE_LOG
876 delete wxLog::SetActiveTarget(new wxLogStderr);
877 #endif // wxUSE_LOG
878
879 } // DatabaseDemoFrame constructor
880
881 DatabaseDemoFrame::~DatabaseDemoFrame()
882 {
883 #if wxUSE_LOG
884 delete wxLog::SetActiveTarget(NULL);
885 #endif // wxUSE_LOG
886 } // DatabaseDemoFrame destructor
887
888
889 void DatabaseDemoFrame::OnCreate(wxCommandEvent& WXUNUSED(event))
890 {
891 wxGetApp().CreateDataTable(false);
892 } // DatabaseDemoFrame::OnCreate()
893
894
895 void DatabaseDemoFrame::OnRecreateTable(wxCommandEvent& WXUNUSED(event))
896 {
897 wxGetApp().CreateDataTable(true);
898 } // DatabaseDemoFrame::OnRecreate()
899
900
901 void DatabaseDemoFrame::OnRecreateIndexes(wxCommandEvent& WXUNUSED(event))
902 {
903 wxGetApp().Contact->GetDb()->RollbackTrans(); // Make sure the current cursor is in a known/stable state
904
905 if (!wxGetApp().Contact->CreateIndexes(true))
906 {
907 while (wxIsBusy())
908 wxEndBusyCursor();
909 wxString tStr;
910 tStr = wxT("Error creating CONTACTS indexes.\nNew indexes will be unavailable.\n\n");
911 wxMessageBox(wxDbLogExtendedErrorMsg(tStr.c_str(),wxGetApp().Contact->GetDb(),__TFILE__,__LINE__),
912 wxT("ODBC Error..."),wxOK | wxICON_EXCLAMATION);
913
914 }
915 else
916 wxMessageBox(wxT("Index(es) were successfully recreated."),wxT("Notice..."),wxOK | wxICON_INFORMATION);
917
918 } // DatabaseDemoFrame::OnRecreateIndexes()
919
920
921 #if wxUSE_GRID
922 void DatabaseDemoFrame::OnDbGridTable(wxCommandEvent& WXUNUSED(event))
923 {
924 DbGridFrame *frame = new DbGridFrame(this);
925 if (frame->Initialize())
926 {
927 frame->Show();
928 }
929 }
930 #endif
931
932 void DatabaseDemoFrame::OnExit(wxCommandEvent& WXUNUSED(event))
933 {
934 Close();
935 } // DatabaseDemoFrame::OnExit()
936
937
938 void DatabaseDemoFrame::OnEditParameters(wxCommandEvent& WXUNUSED(event))
939 {
940 if ((pEditorDlg->mode != mCreate) && (pEditorDlg->mode != mEdit))
941 BuildParameterDialog(this);
942 else
943 wxMessageBox(wxT("Cannot change database parameters while creating or editing a record"),wxT("Notice..."),wxOK | wxICON_INFORMATION);
944 } // DatabaseDemoFrame::OnEditParameters()
945
946
947 void DatabaseDemoFrame::OnAbout(wxCommandEvent& WXUNUSED(event))
948 {
949 wxMessageBox(wxT("wxWidgets sample program for database classes\n\nContributed on 27 July 1998"),wxT("About..."),wxOK | wxICON_INFORMATION);
950 } // DatabaseDemoFrame::OnAbout()
951
952
953 // Put any additional checking necessary to make certain it is alright
954 // to close the program here that is not done elsewhere
955 void DatabaseDemoFrame::OnCloseWindow(wxCloseEvent& event)
956 {
957 // Clean up time
958 if (pEditorDlg && pEditorDlg->Close())
959 pEditorDlg = NULL;
960 else
961 {
962 if (pEditorDlg)
963 {
964 event.Veto();
965 return;
966 }
967 }
968
969 wxDELETE(wxGetApp().Contact);
970
971 // This function will close all the connections to the database that have been
972 // previously cached.
973 wxDbCloseConnections();
974
975 // Deletion of the wxDbConnectInf instance must be the LAST thing done that
976 // has anything to do with the database. Deleting this before disconnecting,
977 // freeing/closing connections, etc will result in a crash!
978 wxDELETE(wxGetApp().DbConnectInf);
979
980 this->Destroy();
981
982 } // DatabaseDemoFrame::OnCloseWindow()
983
984
985 void DatabaseDemoFrame::BuildEditorDialog()
986 {
987 pEditorDlg = NULL;
988 pEditorDlg = new CeditorDlg(this);
989 if (pEditorDlg)
990 {
991 pEditorDlg->Initialize();
992 if (!pEditorDlg->initialized)
993 {
994 pEditorDlg->Close();
995 pEditorDlg = NULL;
996 wxMessageBox(wxT("Unable to initialize the editor dialog for some reason"),wxT("Error..."),wxOK | wxICON_EXCLAMATION);
997 Close();
998 }
999 }
1000 else
1001 {
1002 wxMessageBox(wxT("Unable to create the editor dialog for some reason"),wxT("Error..."),wxOK | wxICON_EXCLAMATION);
1003 Close();
1004 }
1005 } // DatabaseDemoFrame::BuildEditorDialog()
1006
1007
1008 void DatabaseDemoFrame::BuildParameterDialog(wxWindow *parent)
1009 {
1010 pParamDlg = new CparameterDlg(parent);
1011
1012 if (!pParamDlg)
1013 wxMessageBox(wxT("Unable to create the parameter dialog for some reason"),wxT("Error..."),wxOK | wxICON_EXCLAMATION);
1014 } // DatabaseDemoFrame::BuildParameterDialog()
1015
1016
1017 /*
1018 * Constructor note: If no wxDb object is passed in, a new connection to the database
1019 * is created for this instance of Ccontact. This can be a slow process depending
1020 * on the database engine being used, and some database engines have a limit on the
1021 * number of connections (either hard limits, or license restricted) so care should
1022 * be used to use as few connections as is necessary.
1023 *
1024 * IMPORTANT: Objects which share a wxDb pointer are ALL acted upon whenever a member
1025 * function of pDb is called (i.e. CommitTrans() or RollbackTrans(), so if modifying
1026 * or creating a table objects which use the same pDb, know that all the objects
1027 * will be committed or rolled back when any of the objects has this function call made.
1028 */
1029 Ccontact::Ccontact (wxDb *pwxDb) : wxDbTable(pwxDb ? pwxDb : wxDbGetConnection(wxGetApp().DbConnectInf),
1030 CONTACT_TABLE_NAME, CONTACT_NO_COLS, (const wxString &)wxEmptyString,
1031 !wxDB_QUERY_ONLY, wxGetApp().DbConnectInf->GetDefaultDir())
1032 {
1033 // This is used to represent whether the database connection should be released
1034 // when this instance of the object is deleted. If using the same connection
1035 // for multiple instance of database objects, then the connection should only be
1036 // released when the last database instance using the connection is deleted
1037 freeDbConn = !pwxDb;
1038
1039 if (GetDb())
1040 GetDb()->SetSqlLogging(sqlLogON);
1041
1042 SetupColumns();
1043
1044 } // Ccontact Constructor
1045
1046
1047 void Ccontact::Initialize()
1048 {
1049 Name[0] = 0;
1050 Addr1[0] = 0;
1051 Addr2[0] = 0;
1052 City[0] = 0;
1053 State[0] = 0;
1054 PostalCode[0] = 0;
1055 Country[0] = 0;
1056 JoinDate.year = 1980;
1057 JoinDate.month = 1;
1058 JoinDate.day = 1;
1059 JoinDate.hour = 0;
1060 JoinDate.minute = 0;
1061 JoinDate.second = 0;
1062 JoinDate.fraction = 0;
1063 NativeLanguage = langENGLISH;
1064 IsDeveloper = false;
1065 Contributions = 0;
1066 LinesOfCode = 0L;
1067 BlobSize = 0L;
1068 memset(Picture, 0, MAX_PICTURE_SIZE);
1069 } // Ccontact::Initialize
1070
1071
1072 Ccontact::~Ccontact()
1073 {
1074 if (freeDbConn)
1075 {
1076 if (!wxDbFreeConnection(GetDb()))
1077 {
1078 wxString tStr;
1079 tStr = wxT("Unable to Free the Ccontact data table handle\n\n");
1080
1081 wxMessageBox(wxDbLogExtendedErrorMsg(tStr.c_str(),wxGetApp().Contact->GetDb(),__TFILE__,__LINE__),
1082 wxT("ODBC Error..."),wxOK | wxICON_EXCLAMATION);
1083 }
1084 }
1085 } // Ccontract destructor
1086
1087
1088 /*
1089 * Handles setting up all the connections for the interface from the wxDbTable
1090 * functions to interface to the data structure used to store records in
1091 * memory, and for all the column definitions that define the table structure
1092 */
1093 void Ccontact::SetupColumns()
1094 {
1095 // NOTE: Columns now are 8 character names, as that is all dBase can support. Longer
1096 // names can be used for other database engines
1097 SetColDefs ( 0,wxT("NAME"), DB_DATA_TYPE_VARCHAR, Name, SQL_C_WXCHAR, sizeof(Name), true, true); // Primary index
1098 SetColDefs ( 1,wxT("ADDRESS1"), DB_DATA_TYPE_VARCHAR, Addr1, SQL_C_WXCHAR, sizeof(Addr1), false,true);
1099 SetColDefs ( 2,wxT("ADDRESS2"), DB_DATA_TYPE_VARCHAR, Addr2, SQL_C_WXCHAR, sizeof(Addr2), false,true);
1100 SetColDefs ( 3,wxT("CITY"), DB_DATA_TYPE_VARCHAR, City, SQL_C_WXCHAR, sizeof(City), false,true);
1101 SetColDefs ( 4,wxT("STATE"), DB_DATA_TYPE_VARCHAR, State, SQL_C_WXCHAR, sizeof(State), false,true);
1102 SetColDefs ( 5,wxT("POSTCODE"), DB_DATA_TYPE_VARCHAR, PostalCode, SQL_C_WXCHAR, sizeof(PostalCode), false,true);
1103 SetColDefs ( 6,wxT("COUNTRY"), DB_DATA_TYPE_VARCHAR, Country, SQL_C_WXCHAR, sizeof(Country), false,true);
1104 SetColDefs ( 7,wxT("JOINDATE"), DB_DATA_TYPE_DATE, &JoinDate, SQL_C_TIMESTAMP, sizeof(JoinDate), false,true);
1105 SetColDefs ( 8,wxT("IS_DEV"), DB_DATA_TYPE_INTEGER, &IsDeveloper, SQL_C_BOOLEAN(IsDeveloper), sizeof(IsDeveloper), false,true);
1106 SetColDefs ( 9,wxT("CONTRIBS"), DB_DATA_TYPE_INTEGER, &Contributions, SQL_C_UTINYINT, sizeof(Contributions), false,true);
1107 SetColDefs (10,wxT("LINE_CNT"), DB_DATA_TYPE_INTEGER, &LinesOfCode, SQL_C_ULONG, sizeof(LinesOfCode), false,true);
1108 SetColDefs (11,wxT("LANGUAGE"), DB_DATA_TYPE_INTEGER, &NativeLanguage, SQL_C_ENUM, sizeof(NativeLanguage), false,true);
1109 #ifdef wxODBC_BLOB_SUPPORT
1110 SetColDefs (12,wxT("PICSIZE"), DB_DATA_TYPE_INTEGER, &BlobSize, SQL_C_ULONG, sizeof(BlobSize), false,true);
1111 SetColDefs (13,wxT("PICTURE"), DB_DATA_TYPE_BLOB, Picture, SQL_C_BINARY, sizeof(Picture), false,true);
1112 #endif
1113 } // Ccontact::SetupColumns
1114
1115
1116 bool Ccontact::CreateIndexes(bool recreate)
1117 {
1118 // This index could easily be accomplished with an "orderBy" clause,
1119 // but is done to show how to construct a non-primary index.
1120 wxString indexName;
1121 wxDbIdxDef idxDef[2];
1122
1123 wxStrcpy(idxDef[0].ColName, wxT("IS_DEV"));
1124 idxDef[0].Ascending = true;
1125
1126 wxStrcpy(idxDef[1].ColName, wxT("NAME"));
1127 idxDef[1].Ascending = true;
1128
1129 indexName = GetTableName();
1130 indexName += wxT("_IDX1");
1131
1132 return CreateIndex(indexName.c_str(), true, 2, idxDef, recreate);
1133
1134 } // Ccontact::CreateIndexes()
1135
1136
1137 /*
1138 * Having a function to do a query on the primary key (and possibly others) is
1139 * very efficient and tighter coding so that it is available where ever the object
1140 * is. Great for use with multiple tables when not using views or outer joins
1141 */
1142 bool Ccontact::FetchByName(const wxString &name)
1143 {
1144 whereStr.Printf(wxT("NAME = '%s'"),name.c_str());
1145 SetWhereClause(whereStr.c_str());
1146 SetOrderByClause(wxEmptyString);
1147
1148 if (!Query())
1149 return(false);
1150
1151 // Fetch the record
1152 return(GetNext());
1153
1154 } // Ccontact::FetchByName()
1155
1156
1157 /*
1158 *
1159 * ************* DIALOGS ***************
1160 *
1161 */
1162
1163
1164 /* CeditorDlg constructor
1165 *
1166 * Creates the dialog used for creating/editing/deleting/copying a Ccontact object.
1167 * This dialog actually is drawn in the main frame of the program
1168 *
1169 * An instance of Ccontact is created - "Contact" - which is used to hold the Ccontact
1170 * object that is currently being worked with.
1171 */
1172
1173 BEGIN_EVENT_TABLE(CeditorDlg, wxPanel)
1174 EVT_BUTTON(wxID_ANY, CeditorDlg::OnButton)
1175 EVT_CLOSE(CeditorDlg::OnCloseWindow)
1176 END_EVENT_TABLE()
1177
1178 CeditorDlg::CeditorDlg(wxWindow *parent) : wxPanel (parent, 0, 0, 537, 530)
1179 {
1180 // Since the ::OnCommand() function is overridden, this prevents the widget
1181 // detection in ::OnCommand() until all widgets have been initialized to prevent
1182 // uninitialized pointers from crashing the program
1183 widgetPtrsSet = false;
1184
1185 initialized = false;
1186
1187 SetMode(mView);
1188
1189 Show(false);
1190 } // CeditorDlg constructor
1191
1192
1193 void CeditorDlg::OnCloseWindow(wxCloseEvent& event)
1194 {
1195 // Clean up time
1196 if ((mode != mCreate) && (mode != mEdit))
1197 {
1198 this->Destroy();
1199 }
1200 else
1201 {
1202 wxMessageBox(wxT("Must finish processing the current record being created/modified before exiting"),wxT("Notice..."),wxOK | wxICON_INFORMATION);
1203 event.Veto();
1204 }
1205 } // CeditorDlg::OnCloseWindow()
1206
1207
1208 void CeditorDlg::OnButton(wxCommandEvent &event)
1209 {
1210 wxWindow *win = (wxWindow*) event.GetEventObject();
1211 OnCommand( *win, event );
1212 } // CeditorDlg::OnButton()
1213
1214
1215 void CeditorDlg::OnCommand(wxWindow& win, wxCommandEvent& WXUNUSED(event))
1216 {
1217 wxString widgetName;
1218
1219 widgetName = win.GetName();
1220
1221 if (!widgetPtrsSet)
1222 return;
1223
1224 if (widgetName == pCreateBtn->GetName())
1225 {
1226 wxGetApp().Contact->Initialize();
1227 PutData();
1228 SetMode( mCreate );
1229 pNameTxt->SetValue(wxEmptyString);
1230 pNameTxt->SetFocus();
1231 return;
1232 }
1233
1234 if (widgetName == pEditBtn->GetName())
1235 {
1236 saveName = wxGetApp().Contact->Name;
1237 SetMode( mEdit );
1238 pNameTxt->SetFocus();
1239 return;
1240 }
1241
1242 if (widgetName == pCopyBtn->GetName())
1243 {
1244 SetMode(mCreate);
1245 pNameTxt->SetValue(wxEmptyString);
1246 pNameTxt->SetFocus();
1247 return;
1248 }
1249
1250 if (widgetName == pDeleteBtn->GetName())
1251 {
1252 bool Ok = (wxMessageBox(wxT("Are you sure?"),wxT("Confirm"),wxYES_NO|wxICON_QUESTION) == wxYES);
1253
1254 if (!Ok)
1255 return;
1256
1257 if (Ok && wxGetApp().Contact->Delete())
1258 {
1259 // NOTE: Deletions are not finalized until a CommitTrans() is performed.
1260 // If the commit were not performed, the program will continue to
1261 // show the table contents as if they were deleted until this instance
1262 // of Ccontact is deleted. If the Commit wasn't performed, the
1263 // database will automatically Rollback the changes when the database
1264 // connection is terminated
1265 wxGetApp().Contact->GetDb()->CommitTrans();
1266
1267 // Try to get the row that followed the just deleted row in the orderBy sequence
1268 if (!GetNextRec())
1269 {
1270 // There was now row (in sequence) after the just deleted row, so get the
1271 // row which preceded the just deleted row
1272 if (!GetPrevRec())
1273 {
1274 // There are now no rows remaining, so clear the dialog widgets
1275 wxGetApp().Contact->Initialize();
1276 PutData();
1277 }
1278 }
1279 SetMode(mode); // force reset of button enable/disable
1280 }
1281 else
1282 // Delete failed
1283 wxGetApp().Contact->GetDb()->RollbackTrans();
1284
1285 SetMode(mView);
1286 return;
1287 }
1288
1289 if (widgetName == pSaveBtn->GetName())
1290 {
1291 Save();
1292 return;
1293 }
1294
1295 if (widgetName == pCancelBtn->GetName())
1296 {
1297 bool Ok = (wxMessageBox(wxT("Are you sure?"),wxT("Confirm"),wxYES_NO|wxICON_QUESTION) == wxYES);
1298
1299 if (!Ok)
1300 return;
1301
1302 if (saveName.empty())
1303 {
1304 wxGetApp().Contact->Initialize();
1305 PutData();
1306 SetMode(mView);
1307 return;
1308 }
1309 else
1310 {
1311 // Requery previous record
1312 if (wxGetApp().Contact->FetchByName(saveName))
1313 {
1314 PutData();
1315 SetMode(mView);
1316 return;
1317 }
1318 }
1319
1320 // Previous record not available, retrieve first record in table
1321 if (wxGetApp().Contact->GetDb()->Dbms() != dbmsPOSTGRES &&
1322 wxGetApp().Contact->GetDb()->Dbms() != dbmsMY_SQL)
1323 {
1324 wxGetApp().Contact->whereStr = wxT("NAME = (SELECT MIN(NAME) FROM ");
1325 wxGetApp().Contact->whereStr += wxGetApp().Contact->GetTableName();
1326 wxGetApp().Contact->whereStr += wxT(")");
1327 wxGetApp().Contact->SetWhereClause(wxGetApp().Contact->whereStr.c_str());
1328 }
1329 else
1330 wxGetApp().Contact->SetWhereClause(wxEmptyString);
1331
1332 if (!wxGetApp().Contact->Query())
1333 {
1334 wxString tStr;
1335 tStr = wxT("ODBC error during Query()\n\n");
1336 wxMessageBox(wxDbLogExtendedErrorMsg(tStr.c_str(),wxGetApp().Contact->GetDb(),__TFILE__,__LINE__),
1337 wxT("ODBC Error..."),wxOK | wxICON_EXCLAMATION);
1338
1339 SetMode(mView);
1340 return;
1341 }
1342 if (wxGetApp().Contact->GetNext()) // Successfully read first record
1343 {
1344 PutData();
1345 SetMode(mView);
1346 return;
1347 }
1348 // No contacts are available, clear dialog
1349 wxGetApp().Contact->Initialize();
1350 PutData();
1351 SetMode(mView);
1352 return;
1353 } // Cancel Button
1354
1355 if (widgetName == pPrevBtn->GetName())
1356 {
1357 if (!GetPrevRec())
1358 wxBell();
1359 return;
1360 } // Prev Button
1361
1362 if (widgetName == pNextBtn->GetName())
1363 {
1364 if (!GetNextRec())
1365 wxBell();
1366 return;
1367 } // Next Button
1368
1369 if (widgetName == pQueryBtn->GetName())
1370 {
1371 // Display the query dialog box
1372 wxChar qryWhere[DB_MAX_WHERE_CLAUSE_LEN+1];
1373 wxStrcpy(qryWhere, (const wxChar*) wxGetApp().Contact->qryWhereStr);
1374 wxChar *tblName[] = {(wxChar *)CONTACT_TABLE_NAME.c_str(), 0};
1375 new CqueryDlg(GetParent(), wxGetApp().Contact->GetDb(), tblName, qryWhere);
1376
1377 // Query the first record in the new record set and
1378 // display it, if the query string has changed.
1379 if (wxStrcmp(qryWhere, (const wxChar*) wxGetApp().Contact->qryWhereStr))
1380 {
1381 wxGetApp().Contact->whereStr.Empty();
1382 wxGetApp().Contact->SetOrderByClause(wxT("NAME"));
1383
1384 if (wxGetApp().Contact->GetDb()->Dbms() != dbmsPOSTGRES &&
1385 wxGetApp().Contact->GetDb()->Dbms() != dbmsMY_SQL)
1386 {
1387 wxGetApp().Contact->whereStr = wxT("NAME = (SELECT MIN(NAME) FROM ");
1388 wxGetApp().Contact->whereStr += CONTACT_TABLE_NAME;
1389 }
1390
1391 // Append the query where string (if there is one)
1392 wxGetApp().Contact->qryWhereStr = qryWhere;
1393 if (wxStrlen(qryWhere))
1394 {
1395 wxGetApp().Contact->whereStr += wxT(" WHERE ");
1396 wxGetApp().Contact->whereStr += wxGetApp().Contact->qryWhereStr;
1397 }
1398 // Close the expression with a right paren
1399 wxGetApp().Contact->whereStr += wxT(")");
1400 // Requery the table
1401 wxGetApp().Contact->SetWhereClause(wxGetApp().Contact->whereStr.c_str());
1402 if (!wxGetApp().Contact->Query())
1403 {
1404 wxString tStr;
1405 tStr = wxT("ODBC error during Query()\n\n");
1406 wxMessageBox(wxDbLogExtendedErrorMsg(tStr.c_str(),wxGetApp().Contact->GetDb(),__TFILE__,__LINE__),
1407 wxT("ODBC Error..."),wxOK | wxICON_EXCLAMATION);
1408
1409 return;
1410 }
1411 // Display the first record from the query set
1412 if (!wxGetApp().Contact->GetNext())
1413 wxGetApp().Contact->Initialize();
1414 PutData();
1415 }
1416
1417 // Enable/Disable the reset button
1418 pResetBtn->Enable(!wxGetApp().Contact->qryWhereStr.empty());
1419
1420 return;
1421 } // Query button
1422
1423
1424 if (widgetName == pResetBtn->GetName())
1425 {
1426 // Clear the additional where criteria established by the query feature
1427 wxGetApp().Contact->qryWhereStr = wxEmptyString;
1428 wxGetApp().Contact->SetOrderByClause(wxT("NAME"));
1429
1430 if (wxGetApp().Contact->GetDb()->Dbms() != dbmsPOSTGRES &&
1431 wxGetApp().Contact->GetDb()->Dbms() != dbmsMY_SQL)
1432 {
1433 wxGetApp().Contact->whereStr = wxT("NAME = (SELECT MIN(NAME) FROM ");
1434 wxGetApp().Contact->whereStr += CONTACT_TABLE_NAME;
1435 wxGetApp().Contact->whereStr += wxT(")");
1436 }
1437
1438 wxGetApp().Contact->SetWhereClause(wxGetApp().Contact->whereStr.c_str());
1439 if (!wxGetApp().Contact->Query())
1440 {
1441 wxString tStr;
1442 tStr = wxT("ODBC error during Query()\n\n");
1443 wxMessageBox(wxDbLogExtendedErrorMsg(tStr.c_str(),wxGetApp().Contact->GetDb(),__TFILE__,__LINE__),
1444 wxT("ODBC Error..."),wxOK | wxICON_EXCLAMATION);
1445 return;
1446 }
1447 if (!wxGetApp().Contact->GetNext())
1448 wxGetApp().Contact->Initialize();
1449 PutData();
1450 pResetBtn->Enable(false);
1451
1452 return;
1453 } // Reset button
1454
1455
1456 if (widgetName == pNameListBtn->GetName())
1457 {
1458 new ClookUpDlg(/* wxWindow *parent */ this,
1459 /* const wxString &windowTitle */ wxT("Select contact name"),
1460 /* const wxString &tableName */ CONTACT_TABLE_NAME,
1461 /* const wxString &dispCol1 */ wxT("NAME"),
1462 /* const wxString &dispCol2 */ wxT("JOINDATE"),
1463 /* const wxString &where */ wxT(""),
1464 /* const wxString &orderBy */ wxT("NAME"),
1465 /* wxDb *pDb */ wxGetApp().READONLY_DB,
1466 /* const wxString &defDir */ wxGetApp().DbConnectInf->GetDefaultDir(),
1467 /* bool distinctValues*/ true,
1468 wxEmptyString, 20);
1469
1470 if (ListDB_Selection && wxStrlen(ListDB_Selection))
1471 {
1472 wxString w = wxT("NAME = '");
1473 w += ListDB_Selection;
1474 w += wxT("'");
1475 GetRec(w);
1476 }
1477
1478 return;
1479 }
1480
1481 if (widgetName == pDataTypesBtn->GetName())
1482 {
1483 CheckSupportForAllDataTypes(wxGetApp().READONLY_DB);
1484 wxMessageBox(wxT("Support datatypes was dumped to stdout."));
1485 return;
1486 } // Data types Button
1487
1488 if (widgetName == pDbDiagsBtn->GetName())
1489 {
1490 DisplayDbDiagnostics(wxGetApp().READONLY_DB);
1491 wxMessageBox(wxT("Diagnostics info was dumped to stdout."));
1492 return;
1493 }
1494
1495 if (widgetName == pCatalogBtn->GetName())
1496 {
1497 if (wxGetApp().Contact->GetDb()->Catalog(wxEmptyString, wxT("catalog.txt")))
1498 wxMessageBox(wxT("The file 'catalog.txt' was created."));
1499 else
1500 wxMessageBox(wxT("Creation of the file 'catalog.txt' failed."));
1501 return;
1502 }
1503
1504 #ifdef wxODBC_BLOB_SUPPORT
1505 if (widgetName == pChooseImageBtn->GetName())
1506 {
1507 OnSelectPict();
1508 }
1509
1510 if (widgetName == pShowImageBtn->GetName())
1511 {
1512 OnShowImage();
1513 }
1514 #endif
1515
1516 } // CeditorDlg::OnCommand()
1517
1518
1519 bool CeditorDlg::Initialize()
1520 {
1521 // Create the data structure and a new database connection.
1522 // (As there is not a pDb being passed in the constructor, a new database
1523 // connection is created)
1524 wxGetApp().Contact = new Ccontact();
1525
1526 if (!wxGetApp().Contact)
1527 {
1528 wxMessageBox(wxT("Unable to instantiate an instance of Ccontact"),wxT("Error..."),wxOK | wxICON_EXCLAMATION);
1529 return false;
1530 }
1531
1532 // Check if the table exists or not. If it doesn't, ask the user if they want to
1533 // create the table. Continue trying to create the table until it exists, or user aborts
1534 while (!wxGetApp().Contact->GetDb()->TableExists(CONTACT_TABLE_NAME,
1535 wxGetApp().DbConnectInf->GetUserID(),
1536 wxGetApp().DbConnectInf->GetDefaultDir()))
1537 {
1538 wxString tStr;
1539 tStr.Printf(wxT("Unable to open the table '%s'. The table may\nneed to be created.\n\nDo you wish to try to create/clear the table?\n\n"),CONTACT_TABLE_NAME.c_str());
1540 bool createTable = (wxMessageBox(tStr.c_str(),wxT("Confirm"),wxYES_NO|wxICON_QUESTION) == wxYES);
1541
1542 if (!createTable)
1543 {
1544 // Close();
1545 return false;
1546 }
1547 else
1548 wxGetApp().CreateDataTable(false);
1549 }
1550
1551 // Tables must be "opened" before anything other than creating/deleting table can be done
1552 if (!wxGetApp().Contact->Open())
1553 {
1554 // Table does exist, or there was some problem opening it. Currently this should
1555 // never fail, except in the case of the table not exisiting or the current
1556 // user has insufficent privileges to access the table
1557 #if 1
1558 // This code is experimenting with a new function that will hopefully be available
1559 // in the 2.4 release. This check will determine whether the open failing was due
1560 // to the table not existing, or the users privileges being insufficient to
1561 // open the table.
1562 if (!wxGetApp().Contact->GetDb()->TablePrivileges(CONTACT_TABLE_NAME, wxT("SELECT"),
1563 wxGetApp().Contact->GetDb()->GetUsername(),
1564 wxGetApp().Contact->GetDb()->GetUsername(),
1565 wxGetApp().DbConnectInf->GetDefaultDir()))
1566 {
1567 wxString tStr;
1568 tStr.Printf(wxT("Unable to open the table '%s' (likely due to\ninsufficient privileges of the logged in user).\n\n"),CONTACT_TABLE_NAME.c_str());
1569
1570 wxMessageBox(wxDbLogExtendedErrorMsg(tStr.c_str(),wxGetApp().Contact->GetDb(),__TFILE__,__LINE__),
1571 wxT("ODBC Error..."),wxOK | wxICON_EXCLAMATION);
1572 }
1573 else
1574 #endif
1575 if (!wxGetApp().Contact->GetDb()->TableExists(CONTACT_TABLE_NAME,
1576 wxGetApp().Contact->GetDb()->GetUsername(),
1577 wxGetApp().DbConnectInf->GetDefaultDir()))
1578 {
1579 wxString tStr;
1580 tStr.Printf(wxT("Unable to open the table '%s' as the table\ndoes not appear to exist in the tablespace available\nto the currently logged in user.\n\n"),CONTACT_TABLE_NAME.c_str());
1581 wxMessageBox(wxDbLogExtendedErrorMsg(tStr.c_str(),wxGetApp().Contact->GetDb(),__TFILE__,__LINE__),
1582 wxT("ODBC Error..."),wxOK | wxICON_EXCLAMATION);
1583 }
1584
1585 return false;
1586 }
1587
1588 // Build the dialog
1589
1590 (void)new wxStaticBox(this, EDITOR_DIALOG_FN_GROUP, wxEmptyString, wxPoint(15, 1), wxSize(497, 69), 0, wxT("FunctionGrp"));
1591 (void)new wxStaticBox(this, EDITOR_DIALOG_SEARCH_GROUP, wxEmptyString, wxPoint(417, 1), wxSize(95, 242), 0, wxT("SearchGrp"));
1592
1593 pCreateBtn = new wxButton(this, EDITOR_DIALOG_CREATE, wxT("&Create"), wxPoint( 25, 21), wxSize( 70, 35), 0, wxDefaultValidator, wxT("CreateBtn"));
1594 pEditBtn = new wxButton(this, EDITOR_DIALOG_EDIT, wxT("&Edit"), wxPoint(102, 21), wxSize( 70, 35), 0, wxDefaultValidator, wxT("EditBtn"));
1595 pDeleteBtn = new wxButton(this, EDITOR_DIALOG_DELETE, wxT("&Delete"), wxPoint(179, 21), wxSize( 70, 35), 0, wxDefaultValidator, wxT("DeleteBtn"));
1596 pCopyBtn = new wxButton(this, EDITOR_DIALOG_COPY, wxT("Cop&y"), wxPoint(256, 21), wxSize( 70, 35), 0, wxDefaultValidator, wxT("CopyBtn"));
1597 pSaveBtn = new wxButton(this, EDITOR_DIALOG_SAVE, wxT("&Save"), wxPoint(333, 21), wxSize( 70, 35), 0, wxDefaultValidator, wxT("SaveBtn"));
1598 pCancelBtn = new wxButton(this, EDITOR_DIALOG_CANCEL, wxT("C&ancel"), wxPoint(430, 21), wxSize( 70, 35), 0, wxDefaultValidator, wxT("CancelBtn"));
1599 pPrevBtn = new wxButton(this, EDITOR_DIALOG_PREV, wxT("<< &Prev"), wxPoint(430, 81), wxSize( 70, 35), 0, wxDefaultValidator, wxT("PrevBtn"));
1600 pNextBtn = new wxButton(this, EDITOR_DIALOG_NEXT, wxT("&Next >>"), wxPoint(430, 121), wxSize( 70, 35), 0, wxDefaultValidator, wxT("NextBtn"));
1601 pQueryBtn = new wxButton(this, EDITOR_DIALOG_QUERY, wxT("&Query"), wxPoint(430, 161), wxSize( 70, 35), 0, wxDefaultValidator, wxT("QueryBtn"));
1602 pResetBtn = new wxButton(this, EDITOR_DIALOG_RESET, wxT("&Reset"), wxPoint(430, 200), wxSize( 70, 35), 0, wxDefaultValidator, wxT("ResetBtn"));
1603 pNameMsg = new wxStaticText(this, EDITOR_DIALOG_NAME_MSG, wxT("Name:"), wxPoint( 17, 80), wxDefaultSize, 0, wxT("NameMsg"));
1604 pNameTxt = new wxTextCtrl(this, EDITOR_DIALOG_NAME_TEXT, wxEmptyString, wxPoint( 17, 97), wxSize(308, 25), 0, wxDefaultValidator, wxT("NameTxt"));
1605 pNameListBtn = new wxButton(this, EDITOR_DIALOG_LOOKUP, wxT("&Lookup"), wxPoint(333, 97), wxSize( 70, 24), 0, wxDefaultValidator, wxT("LookupBtn"));
1606 pAddress1Msg = new wxStaticText(this, EDITOR_DIALOG_ADDRESS1_MSG, wxT("Address:"), wxPoint( 17, 130), wxDefaultSize, 0, wxT("Address1Msg"));
1607 pAddress1Txt = new wxTextCtrl(this, EDITOR_DIALOG_ADDRESS2_TEXT, wxEmptyString, wxPoint( 17, 147), wxSize(308, 25), 0, wxDefaultValidator, wxT("Address1Txt"));
1608 pAddress2Msg = new wxStaticText(this, EDITOR_DIALOG_ADDRESS2_MSG, wxT("Address:"), wxPoint( 17, 180), wxDefaultSize, 0, wxT("Address2Msg"));
1609 pAddress2Txt = new wxTextCtrl(this, EDITOR_DIALOG_ADDRESS2_TEXT, wxEmptyString, wxPoint( 17, 197), wxSize(308, 25), 0, wxDefaultValidator, wxT("Address2Txt"));
1610 pCityMsg = new wxStaticText(this, EDITOR_DIALOG_CITY_MSG, wxT("City:"), wxPoint( 17, 230), wxDefaultSize, 0, wxT("CityMsg"));
1611 pCityTxt = new wxTextCtrl(this, EDITOR_DIALOG_CITY_TEXT, wxEmptyString, wxPoint( 17, 247), wxSize(225, 25), 0, wxDefaultValidator, wxT("CityTxt"));
1612 pStateMsg = new wxStaticText(this, EDITOR_DIALOG_STATE_MSG, wxT("State:"), wxPoint(250, 230), wxDefaultSize, 0, wxT("StateMsg"));
1613 pStateTxt = new wxTextCtrl(this, EDITOR_DIALOG_STATE_TEXT, wxEmptyString, wxPoint(250, 247), wxSize(153, 25), 0, wxDefaultValidator, wxT("StateTxt"));
1614 pCountryMsg = new wxStaticText(this, EDITOR_DIALOG_COUNTRY_MSG, wxT("Country:"), wxPoint( 17, 280), wxDefaultSize, 0, wxT("CountryMsg"));
1615 pCountryTxt = new wxTextCtrl(this, EDITOR_DIALOG_COUNTRY_TEXT, wxEmptyString, wxPoint( 17, 297), wxSize(225, 25), 0, wxDefaultValidator, wxT("CountryTxt"));
1616 pPostalCodeMsg = new wxStaticText(this, EDITOR_DIALOG_POSTAL_MSG, wxT("Postal Code:"),wxPoint(250, 280), wxDefaultSize, 0, wxT("PostalCodeMsg"));
1617 pPostalCodeTxt = new wxTextCtrl(this, EDITOR_DIALOG_POSTAL_TEXT, wxEmptyString, wxPoint(250, 297), wxSize(153, 25), 0, wxDefaultValidator, wxT("PostalCodeTxt"));
1618
1619 wxString choice_strings[5];
1620 choice_strings[0] = wxT("English");
1621 choice_strings[1] = wxT("French");
1622 choice_strings[2] = wxT("German");
1623 choice_strings[3] = wxT("Spanish");
1624 choice_strings[4] = wxT("Other");
1625
1626 pNativeLangChoice = new wxChoice(this, EDITOR_DIALOG_LANG_CHOICE, wxPoint( 17, 346), wxSize(277, wxDefaultCoord), 5, choice_strings);
1627 pNativeLangMsg = new wxStaticText(this, EDITOR_DIALOG_LANG_MSG, wxT("Native language:"), wxPoint( 17, 330), wxDefaultSize, 0, wxT("NativeLangMsg"));
1628
1629 wxString radio_strings[2];
1630 radio_strings[0] = wxT("No");
1631 radio_strings[1] = wxT("Yes");
1632 pDeveloperRadio = new wxRadioBox(this,EDITOR_DIALOG_DEVELOPER, wxT("Developer:"), wxPoint(303, 330), wxDefaultSize, 2, radio_strings, 2, wxHORIZONTAL);
1633 pJoinDateMsg = new wxStaticText(this, EDITOR_DIALOG_JOIN_MSG, wxT("Date joined:"), wxPoint( 17, 380), wxDefaultSize, 0, wxT("JoinDateMsg"));
1634 pJoinDateTxt = new wxTextCtrl(this, EDITOR_DIALOG_JOIN_TEXT, wxEmptyString, wxPoint( 17, 397), wxSize(150, 25), 0, wxDefaultValidator, wxT("JoinDateTxt"));
1635 pContribMsg = new wxStaticText(this, EDITOR_DIALOG_CONTRIB_MSG,wxT("Contributions:"), wxPoint(175, 380), wxDefaultSize, 0, wxT("ContribMsg"));
1636 pContribTxt = new wxTextCtrl(this, EDITOR_DIALOG_CONTRIB_TEXT, wxEmptyString, wxPoint(175, 397), wxSize(120, 25), 0, wxDefaultValidator, wxT("ContribTxt"));
1637 pLinesMsg = new wxStaticText(this, EDITOR_DIALOG_LINES_MSG, wxT("Lines of code:"), wxPoint(303, 380), wxDefaultSize, 0, wxT("LinesMsg"));
1638 pLinesTxt = new wxTextCtrl(this, EDITOR_DIALOG_LINES_TEXT, wxEmptyString, wxPoint(303, 397), wxSize(100, 25), 0, wxDefaultValidator, wxT("LinesTxt"));
1639
1640 pCatalogBtn = new wxButton(this, EDITOR_DIALOG_CATALOG, wxT("Catalo&g"), wxPoint(430, 287), wxSize( 70, 35), 0, wxDefaultValidator, wxT("CatalogBtn"));
1641 pDataTypesBtn = new wxButton(this, EDITOR_DIALOG_DATATYPES, wxT("Data&types"), wxPoint(430, 337), wxSize( 70, 35), 0, wxDefaultValidator, wxT("DataTypesBtn"));
1642 pDbDiagsBtn = new wxButton(this, EDITOR_DIALOG_DB_DIAGS, wxT("DB Dia&gs"), wxPoint(430, 387), wxSize( 70, 35), 0, wxDefaultValidator, wxT("DbDiagsBtn"));
1643
1644 #ifdef wxODBC_BLOB_SUPPORT
1645 pPictureMsg = new wxStaticText(this, EDITOR_DIALOG_PIC_MSG, wxT("Picture:"), wxPoint( 17,430), wxDefaultSize, 0, wxT("PicMsg"));
1646 pPictSizeMsg = new wxStaticText(this, EDITOR_DIALOG_PICSIZE_MSG, wxT("Picture Bytes:"), wxPoint(175,430), wxDefaultSize, 0, wxT("PicSizeMsg"));
1647 pChooseImageBtn = new wxButton(this, EDITOR_DIALOG_PIC_BROWSE, wxT("Select..."), wxPoint( 17,447), wxSize( 70, 24), 0, wxDefaultValidator, wxT("PicBrowseBtn"));
1648 pShowImageBtn = new wxButton(this, EDITOR_DIALOG_PIC_SHOW, wxT("Show..."), wxPoint( 97,447), wxSize( 70, 24), 0, wxDefaultValidator, wxT("PictShowBtn"));
1649 pPictSizeTxt = new wxTextCtrl(this, EDITOR_DIALOG_PIC_SIZE_TEXT, wxEmptyString, wxPoint(175,447), wxSize(120, 25), 0, wxDefaultValidator, wxT("PictSizeTxt"));
1650 #endif
1651
1652 // Now that all the widgets on the panel are created, its safe to allow ::OnCommand() to
1653 // handle all widget processing
1654 widgetPtrsSet = true;
1655
1656 // Setup the orderBy and where clauses to return back a single record as the result set,
1657 // as there will only be one record being shown on the dialog at a time, this optimizes
1658 // network traffic by only returning a one row result
1659
1660 wxGetApp().Contact->SetOrderByClause(wxT("NAME")); // field name to sort by
1661
1662 // The wxString "whereStr" is not a member of the wxDbTable object, it is a member variable
1663 // specifically in the Ccontact class. It is used here for simpler construction of a varying
1664 // length string, and then after the string is built, the wxDbTable member variable "where" is
1665 // assigned the pointer to the constructed string.
1666 //
1667 // The constructed where clause below has a sub-query within it "SELECT MIN(NAME) FROM %s"
1668 // to achieve a single row (in this case the first name in alphabetical order).
1669
1670 if (wxGetApp().Contact->GetDb()->Dbms() != dbmsPOSTGRES &&
1671 wxGetApp().Contact->GetDb()->Dbms() != dbmsMY_SQL)
1672 {
1673 wxGetApp().Contact->whereStr.Printf(wxT("NAME = (SELECT MIN(NAME) FROM %s)"),
1674 wxGetApp().Contact->GetTableName().c_str());
1675 // NOTE: (const wxChar*) returns a pointer which may not be valid later, so this is short term use only
1676 wxGetApp().Contact->SetWhereClause(wxGetApp().Contact->whereStr);
1677 }
1678 else
1679 wxGetApp().Contact->SetWhereClause(wxEmptyString);
1680
1681 // Perform the Query to get the result set.
1682 // NOTE: If there are no rows returned, that is a valid result, so Query() would return true.
1683 // Only if there is a database error will Query() come back as false
1684 if (!wxGetApp().Contact->Query())
1685 {
1686 wxString tStr;
1687 tStr = wxT("ODBC error during Query()\n\n");
1688 wxMessageBox(wxDbLogExtendedErrorMsg(tStr.c_str(),wxGetApp().Contact->GetDb(),__TFILE__,__LINE__),
1689 wxT("ODBC Error..."),wxOK | wxICON_EXCLAMATION);
1690 return false;
1691 }
1692
1693 // Since Query succeeded, now get the row that was returned
1694 if (!wxGetApp().Contact->GetNext())
1695 // If the GetNext() failed at this point, then there are no rows to retrieve,
1696 // so clear the values in the members of "Contact" so that PutData() blanks the
1697 // widgets on the dialog
1698 wxGetApp().Contact->Initialize();
1699 /*
1700 wxGetApp().Contact->GetDb()->RollbackTrans();
1701 */
1702 SetMode(mView);
1703 PutData();
1704
1705 Show(true);
1706
1707 initialized = true;
1708 return true;
1709 } // CeditorDlg::Initialize()
1710
1711 #ifdef wxODBC_BLOB_SUPPORT
1712
1713 void CeditorDlg::OnSelectPict()
1714 {
1715 wxFileDialog dlg(this, wxT("Choose an image file less than 60K"), wxEmptyString, wxEmptyString, wxT("JPEG files (*.jpg)|*.jpg|GIF files (*.gif)|*.gif|BMP files (*.bmp)|*.bmp|All Files (*.*)|*.*"), wxFD_OPEN);
1716
1717 if (dlg.ShowModal() == wxID_OK)
1718 {
1719 wxFile file(dlg.GetPath());
1720
1721 if (file.IsOpened())
1722 {
1723 // assume not huge file in sample
1724 long iSize = (long)file.Length();
1725
1726 if ((iSize > 0) && (iSize < MAX_PICTURE_SIZE))
1727 {
1728 wxGetApp().Contact->BlobSize = (size_t)iSize;
1729
1730 memset(wxGetApp().Contact->Picture, 0, MAX_PICTURE_SIZE);
1731
1732 wxFileOffset iReadSize = file.Read(wxGetApp().Contact->Picture, (size_t)iSize);
1733
1734 if (iReadSize < iSize)
1735 wxMessageBox(wxT("Something bad happened while reading..."), wxT("BLOB Loading Error"), wxOK | wxICON_EXCLAMATION);
1736
1737 wxString tStr;
1738 tStr.Printf(wxT("%ld"),iSize);
1739 pPictSizeTxt->SetValue(tStr);
1740 }
1741 else
1742 wxMessageBox(wxT("Selected File is TOO BIG. 60k is the max image size"), wxT("BLOB Loading Error"), wxOK | wxICON_EXCLAMATION);
1743 }
1744 else
1745 wxMessageBox(wxT("Unable to open the requested image file"), wxT("File Access Error"), wxOK | wxICON_EXCLAMATION);
1746 }
1747 }
1748
1749 void CeditorDlg::OnShowImage()
1750 {
1751 if (wxGetApp().Contact->BlobSize > 0)
1752 {
1753 CimageDlg dlg(this, wxGetApp().Contact->Picture, wxGetApp().Contact->BlobSize);
1754
1755 dlg.ShowModal();
1756 }
1757 }
1758
1759 #endif
1760
1761 void CeditorDlg::FieldsEditable()
1762 {
1763 if (!widgetPtrsSet)
1764 return;
1765
1766 pNameTxt->Enable((mode == mCreate) || (mode == mEdit));
1767 pAddress1Txt->Enable((mode == mCreate) || (mode == mEdit));
1768 pAddress2Txt->Enable((mode == mCreate) || (mode == mEdit));
1769 pCityTxt->Enable((mode == mCreate) || (mode == mEdit));
1770 pStateTxt->Enable((mode == mCreate) || (mode == mEdit));
1771 pPostalCodeTxt->Enable((mode == mCreate) || (mode == mEdit));
1772 pCountryTxt->Enable((mode == mCreate) || (mode == mEdit));
1773
1774 pJoinDateTxt->Enable((mode == mCreate) || (mode == mEdit));
1775 pContribTxt->Enable((mode == mCreate) || (mode == mEdit));
1776 pLinesTxt->Enable((mode == mCreate) || (mode == mEdit));
1777 pNativeLangChoice->Enable((mode == mCreate) || (mode == mEdit));
1778 pDeveloperRadio->Enable((mode == mCreate) || (mode == mEdit));
1779
1780 #ifdef wxODBC_BLOB_SUPPORT
1781 pPictSizeTxt->Enable(false);
1782 pChooseImageBtn->Enable((mode == mCreate) || (mode == mEdit));
1783 pShowImageBtn->Enable(wxGetApp().Contact && wxGetApp().Contact->BlobSize > 0); //((mode == mCreate) || (mode == mEdit));
1784 #endif
1785
1786 } // CeditorDlg::FieldsEditable()
1787
1788
1789 void CeditorDlg::SetMode(enum DialogModes m)
1790 {
1791 bool edit = false;
1792
1793 mode = m;
1794 switch (mode)
1795 {
1796 case mCreate:
1797 case mEdit:
1798 edit = true;
1799 break;
1800 case mView:
1801 case mSearch:
1802 edit = false;
1803 break;
1804 default:
1805 break;
1806 };
1807
1808 if (widgetPtrsSet)
1809 {
1810 pCreateBtn->Enable( !edit );
1811 pEditBtn->Enable( !edit && (wxStrcmp(wxGetApp().Contact->Name, wxEmptyString) != 0) );
1812 pDeleteBtn->Enable( !edit && (wxStrcmp(wxGetApp().Contact->Name, wxEmptyString)!=0) );
1813 pCopyBtn->Enable( !edit && (wxStrcmp(wxGetApp().Contact->Name, wxEmptyString)!=0) );
1814 pSaveBtn->Enable( edit );
1815 pCancelBtn->Enable( edit );
1816 pPrevBtn->Enable( !edit );
1817 pNextBtn->Enable( !edit );
1818 pQueryBtn->Enable( !edit );
1819 pResetBtn->Enable( !edit && !wxGetApp().Contact->qryWhereStr.empty() );
1820 pNameListBtn->Enable( !edit );
1821 }
1822
1823 FieldsEditable();
1824 } // CeditorDlg::SetMode()
1825
1826
1827 bool CeditorDlg::PutData()
1828 {
1829 wxString tStr;
1830
1831 pNameTxt->SetValue(wxGetApp().Contact->Name);
1832 pAddress1Txt->SetValue(wxGetApp().Contact->Addr1);
1833 pAddress2Txt->SetValue(wxGetApp().Contact->Addr2);
1834 pCityTxt->SetValue(wxGetApp().Contact->City);
1835 pStateTxt->SetValue(wxGetApp().Contact->State);
1836 pCountryTxt->SetValue(wxGetApp().Contact->Country);
1837 pPostalCodeTxt->SetValue(wxGetApp().Contact->PostalCode);
1838
1839 tStr.Printf(wxT("%d/%d/%d"),wxGetApp().Contact->JoinDate.month,wxGetApp().Contact->JoinDate.day,wxGetApp().Contact->JoinDate.year);
1840 pJoinDateTxt->SetValue(tStr);
1841
1842 tStr.Printf(wxT("%d"),wxGetApp().Contact->Contributions);
1843 pContribTxt->SetValue(tStr);
1844
1845 tStr.Printf(wxT("%lu"),wxGetApp().Contact->LinesOfCode);
1846 pLinesTxt->SetValue(tStr);
1847
1848 pNativeLangChoice->SetSelection(wxGetApp().Contact->NativeLanguage);
1849
1850 pDeveloperRadio->SetSelection(wxGetApp().Contact->IsDeveloper);
1851
1852 #ifdef wxODBC_BLOB_SUPPORT
1853 tStr.Printf(wxT("%lu"),wxGetApp().Contact->BlobSize);
1854 pPictSizeTxt->SetValue(tStr);
1855 pShowImageBtn->Enable(wxGetApp().Contact->BlobSize > 0);
1856 #endif
1857
1858 return true;
1859 } // Ceditor::PutData()
1860
1861
1862 /*
1863 * Reads the data out of all the widgets on the dialog. Some data evaluation is done
1864 * to ensure that there is a name entered and that the date field is valid.
1865 *
1866 * A return value of true means that valid data was retrieved from the dialog, otherwise
1867 * invalid data was found (and a message was displayed telling the user what to fix), and
1868 * the data was not placed into the appropraite fields of Ccontact
1869 */
1870 bool CeditorDlg::GetData()
1871 {
1872 // Validate that the data currently entered into the widgets is valid data
1873
1874 wxString tStr;
1875 tStr = pNameTxt->GetValue();
1876 if (!wxStrcmp((const wxChar*) tStr, wxEmptyString))
1877 {
1878 wxMessageBox(wxT("A name is required for entry into the contact table"), wxT("Notice..."), wxOK | wxICON_INFORMATION);
1879 return false;
1880 }
1881
1882 bool invalid = false;
1883 int mm = 1,dd = 1,yyyy = 2001;
1884 int first, second;
1885
1886 tStr = pJoinDateTxt->GetValue();
1887 if (tStr.Freq(wxT('/')) != 2)
1888 invalid = true;
1889
1890 // Find the month, day, and year tokens
1891 if (!invalid)
1892 {
1893 first = tStr.First(wxT('/'));
1894 second = tStr.Last(wxT('/'));
1895
1896 mm = wxAtoi(tStr.SubString(0,first));
1897 dd = wxAtoi(tStr.SubString(first+1,second));
1898 yyyy = wxAtoi(tStr.SubString(second+1,tStr.Length()-1));
1899
1900 invalid = !(mm && dd && yyyy);
1901 }
1902
1903 // Force Year 2000 compliance
1904 if (!invalid && (yyyy < 1000))
1905 invalid = true;
1906
1907 // Check the token ranges for validity
1908 if (!invalid)
1909 {
1910 if (yyyy > 9999)
1911 invalid = true;
1912 else if ((mm < 1) || (mm > 12))
1913 invalid = true;
1914 else
1915 {
1916 if (dd < 1)
1917 invalid = true;
1918 else
1919 {
1920 int days[12] = {31,28,31,30,31,30,
1921 31,31,30,31,30,31};
1922 if (dd > days[mm-1])
1923 {
1924 invalid = true;
1925 if ((dd == 29) && (mm == 2))
1926 {
1927 if (((yyyy % 4) == 0) && (((yyyy % 100) != 0) || ((yyyy % 400) == 0)))
1928 invalid = false;
1929 }
1930 }
1931 }
1932 }
1933 }
1934
1935 if (!invalid)
1936 {
1937 wxGetApp().Contact->JoinDate.month = (unsigned short) mm;
1938 wxGetApp().Contact->JoinDate.day = (unsigned short) dd;
1939 wxGetApp().Contact->JoinDate.year = (short) yyyy;
1940 }
1941 else
1942 {
1943 wxMessageBox(wxT("Improper date format. Please check the date\nspecified and try again.\n\nNOTE: Dates are in american format (MM/DD/YYYY)"),wxT("Notice..."),wxOK | wxICON_INFORMATION);
1944 return false;
1945 }
1946
1947 tStr = pNameTxt->GetValue();
1948 wxStrcpy(wxGetApp().Contact->Name,(const wxChar*) tStr);
1949 wxStrcpy(wxGetApp().Contact->Addr1,pAddress1Txt->GetValue());
1950 wxStrcpy(wxGetApp().Contact->Addr2,pAddress2Txt->GetValue());
1951 wxStrcpy(wxGetApp().Contact->City,pCityTxt->GetValue());
1952 wxStrcpy(wxGetApp().Contact->State,pStateTxt->GetValue());
1953 wxStrcpy(wxGetApp().Contact->Country,pCountryTxt->GetValue());
1954 wxStrcpy(wxGetApp().Contact->PostalCode,pPostalCodeTxt->GetValue());
1955
1956 wxGetApp().Contact->Contributions = (UCHAR)wxAtoi(pContribTxt->GetValue());
1957 wxGetApp().Contact->LinesOfCode = wxAtol(pLinesTxt->GetValue());
1958
1959 wxGetApp().Contact->NativeLanguage = (enum Language) pNativeLangChoice->GetSelection();
1960 wxGetApp().Contact->IsDeveloper = pDeveloperRadio->GetSelection() > 0;
1961
1962 return true;
1963 } // CeditorDlg::GetData()
1964
1965
1966 /*
1967 * Retrieve data from the dialog, verify the validity of the data, and if it is valid,
1968 * try to insert/update the data to the table based on the current 'mode' the dialog
1969 * is set to.
1970 *
1971 * A return value of true means the insert/update was completed successfully, a return
1972 * value of false means that Save() failed. If returning false, then this function
1973 * has displayed a detailed error message for the user.
1974 */
1975 bool CeditorDlg::Save()
1976 {
1977 bool failed = false;
1978
1979 // Read the data in the widgets of the dialog to get the user's data
1980 if (!GetData())
1981 failed = true;
1982
1983 // Perform any other required validations necessary before saving
1984 if (!failed)
1985 {
1986 wxBeginBusyCursor();
1987
1988 if (mode == mCreate)
1989 {
1990 RETCODE result = (RETCODE)wxGetApp().Contact->Insert();
1991
1992 failed = (result != DB_SUCCESS);
1993 if (failed)
1994 {
1995 // Some errors may be expected, like a duplicate key, so handle those instances with
1996 // specific error messages.
1997 if (result == DB_ERR_INTEGRITY_CONSTRAINT_VIOL)
1998 {
1999 wxString tStr;
2000 tStr = wxT("A duplicate key value already exists in the table.\nUnable to save record\n\n");
2001 wxMessageBox(wxDbLogExtendedErrorMsg(tStr.c_str(),wxGetApp().Contact->GetDb(),__TFILE__,__LINE__),
2002 wxT("ODBC Error..."),wxOK | wxICON_EXCLAMATION);
2003 }
2004 else
2005 {
2006 // Some other unexpected error occurred
2007 wxString tStr;
2008 tStr = wxT("Database insert failed\n\n");
2009 wxMessageBox(wxDbLogExtendedErrorMsg(tStr.c_str(),wxGetApp().Contact->GetDb(),__TFILE__,__LINE__),
2010 wxT("ODBC Error..."),wxOK | wxICON_EXCLAMATION);
2011 }
2012 }
2013 }
2014 else // mode == mEdit
2015 {
2016 wxGetApp().Contact->GetDb()->RollbackTrans();
2017 wxGetApp().Contact->whereStr.Printf(wxT("NAME = '%s'"),saveName.c_str());
2018 if (!wxGetApp().Contact->UpdateWhere(wxGetApp().Contact->whereStr))
2019 {
2020 wxString tStr;
2021 tStr = wxT("Database update failed\n\n");
2022 wxMessageBox(wxDbLogExtendedErrorMsg(tStr.c_str(),wxGetApp().Contact->GetDb(),__TFILE__,__LINE__),
2023 wxT("ODBC Error..."),wxOK | wxICON_EXCLAMATION);
2024 failed = true;
2025 }
2026 }
2027
2028 if (!failed)
2029 {
2030 wxGetApp().Contact->GetDb()->CommitTrans();
2031 SetMode(mView); // Sets the dialog mode back to viewing after save is successful
2032 }
2033 else
2034 wxGetApp().Contact->GetDb()->RollbackTrans();
2035
2036 wxEndBusyCursor();
2037 }
2038
2039 return !failed;
2040 } // CeditorDlg::Save()
2041
2042
2043 /*
2044 * Where this program is only showing a single row at a time in the dialog,
2045 * a special where clause must be built to find just the single row which,
2046 * in sequence, would follow the currently displayed row.
2047 */
2048 bool CeditorDlg::GetNextRec()
2049 {
2050 wxString w;
2051
2052 if (wxGetApp().Contact->GetDb()->Dbms() != dbmsPOSTGRES &&
2053 wxGetApp().Contact->GetDb()->Dbms() != dbmsMY_SQL)
2054 {
2055 w = wxT("NAME = (SELECT MIN(NAME) FROM ");
2056 w += wxGetApp().Contact->GetTableName();
2057 w += wxT(" WHERE NAME > '");
2058 }
2059 else
2060 w = wxT("(NAME > '");
2061
2062 w += wxGetApp().Contact->Name;
2063 w += wxT("'");
2064
2065 // If a query where string is currently set, append that criteria
2066 if (!wxGetApp().Contact->qryWhereStr.empty())
2067 {
2068 w += wxT(" AND (");
2069 w += wxGetApp().Contact->qryWhereStr;
2070 w += wxT(")");
2071 }
2072
2073 w += wxT(")");
2074 return(GetRec(w));
2075
2076 } // CeditorDlg::GetNextRec()
2077
2078
2079 /*
2080 * Where this program is only showing a single row at a time in the dialog,
2081 * a special where clause must be built to find just the single row which,
2082 * in sequence, would precede the currently displayed row.
2083 */
2084 bool CeditorDlg::GetPrevRec()
2085 {
2086 wxString w;
2087
2088 if (wxGetApp().Contact->GetDb()->Dbms() != dbmsPOSTGRES &&
2089 wxGetApp().Contact->GetDb()->Dbms() != dbmsMY_SQL)
2090 {
2091 w = wxT("NAME = (SELECT MAX(NAME) FROM ");
2092 w += wxGetApp().Contact->GetTableName();
2093 w += wxT(" WHERE NAME < '");
2094 }
2095 else
2096 w = wxT("(NAME < '");
2097
2098 w += wxGetApp().Contact->Name;
2099 w += wxT("'");
2100
2101 // If a query where string is currently set, append that criteria
2102 if (!wxGetApp().Contact->qryWhereStr.empty())
2103 {
2104 w += wxT(" AND (");
2105 w += wxGetApp().Contact->qryWhereStr;
2106 w += wxT(")");
2107 }
2108
2109 w += wxT(")");
2110
2111 return(GetRec(w));
2112
2113 } // CeditorDlg::GetPrevRec()
2114
2115
2116 /*
2117 * This function is here to avoid duplicating this same code in both the
2118 * GetPrevRec() and GetNextRec() functions
2119 */
2120 bool CeditorDlg::GetRec(const wxString &whereStr)
2121 {
2122 wxGetApp().Contact->SetWhereClause(whereStr);
2123 wxGetApp().Contact->SetOrderByClause(wxT("NAME"));
2124
2125 if (!wxGetApp().Contact->Query())
2126 {
2127 wxString tStr;
2128 tStr = wxT("ODBC error during Query()\n\n");
2129 wxMessageBox(wxDbLogExtendedErrorMsg(tStr.c_str(),wxGetApp().Contact->GetDb(),__TFILE__,__LINE__),
2130 wxT("ODBC Error..."),wxOK | wxICON_EXCLAMATION);
2131
2132 return(false);
2133 }
2134
2135 if (wxGetApp().Contact->GetNext())
2136 {
2137 PutData();
2138 return(true);
2139 }
2140 else
2141 return(false);
2142 } // CeditorDlg::GetRec()
2143
2144
2145
2146 /*
2147 * CparameterDlg constructor
2148 */
2149
2150 BEGIN_EVENT_TABLE(CparameterDlg, wxDialog)
2151 EVT_BUTTON(PARAMETER_DIALOG_SAVE, CparameterDlg::OnButton)
2152 EVT_BUTTON(PARAMETER_DIALOG_CANCEL, CparameterDlg::OnButton)
2153 EVT_CLOSE(CparameterDlg::OnCloseWindow)
2154 END_EVENT_TABLE()
2155
2156 CparameterDlg::CparameterDlg(wxWindow *parent) : wxDialog (parent, PARAMETER_DIALOG, wxT("ODBC parameter settings"), wxDefaultPosition, wxSize(400, 325))
2157 {
2158 // Since the ::OnCommand() function is overridden, this prevents the widget
2159 // detection in ::OnCommand() until all widgets have been initialized to prevent
2160 // uninitialized pointers from crashing the program
2161 widgetPtrsSet = false;
2162
2163 pParamODBCSourceMsg = new wxStaticText(this, PARAMETER_DIALOG_SOURCE_MSG, wxT("ODBC data sources:"), wxPoint( 10, 10), wxDefaultSize, 0, wxT("ParamODBCSourceMsg"));
2164 pParamODBCSourceList = new wxListBox(this, PARAMETER_DIALOG_SOURCE_LISTBOX, wxPoint( 10, 29), wxSize(285, 150), 0, 0, wxLB_SINGLE|wxLB_ALWAYS_SB, wxDefaultValidator, wxT("ParamODBCSourceList"));
2165 pParamUserNameMsg = new wxStaticText(this, PARAMETER_DIALOG_NAME_MSG, wxT("Database user name:"), wxPoint( 10, 193), wxDefaultSize, 0, wxT("ParamUserNameMsg"));
2166 pParamUserNameTxt = new wxTextCtrl(this, PARAMETER_DIALOG_NAME_TEXT, wxEmptyString, wxPoint(10, 209), wxSize( 140, 25), 0, wxDefaultValidator, wxT("ParamUserNameTxt"));
2167 pParamPasswordMsg = new wxStaticText(this, PARAMETER_DIALOG_PASSWORD_MSG, wxT("Password:"), wxPoint(156, 193), wxDefaultSize, 0, wxT("ParamPasswordMsg"));
2168 pParamPasswordTxt = new wxTextCtrl(this, PARAMETER_DIALOG_PASSWORD_TEXT, wxEmptyString, wxPoint(156, 209), wxSize( 140, 25), 0, wxDefaultValidator, wxT("ParamPasswordTxt"));
2169 pParamDirPathMsg = new wxStaticText(this, PARAMETER_DIALOG_DIRPATH_MSG, wxT("Directory:"), wxPoint( 10, 243), wxDefaultSize, 0, wxT("ParamDirPathMsg"));
2170 pParamDirPathTxt = new wxTextCtrl(this, PARAMETER_DIALOG_DIRPATH_TEXT, wxEmptyString, wxPoint( 10, 259), wxSize(140, 25), 0, wxDefaultValidator, wxT("ParamDirPathTxt"));
2171 pParamSaveBtn = new wxButton(this, PARAMETER_DIALOG_SAVE, wxT("&Save"), wxPoint(310, 21), wxSize( 70, 35), 0, wxDefaultValidator, wxT("ParamSaveBtn"));
2172 pParamCancelBtn = new wxButton(this, PARAMETER_DIALOG_CANCEL, wxT("C&ancel"), wxPoint(310, 66), wxSize( 70, 35), 0, wxDefaultValidator, wxT("ParamCancelBtn"));
2173
2174 // Now that all the widgets on the panel are created, its safe to allow ::OnCommand() to
2175 // handle all widget processing
2176 widgetPtrsSet = true;
2177
2178 saved = false;
2179 savedParamSettings = wxGetApp().params;
2180
2181 Centre(wxBOTH);
2182 PutData();
2183 ShowModal();
2184 } // CparameterDlg constructor
2185
2186
2187 void CparameterDlg::OnCloseWindow(wxCloseEvent& event)
2188 {
2189 // Put any additional checking necessary to make certain it is alright
2190 // to close the program here that is not done elsewhere
2191 if (!saved)
2192 {
2193 bool Ok = (wxMessageBox(wxT("No changes have been saved.\n\nAre you sure you wish exit the parameter screen?"),wxT("Confirm"),wxYES_NO|wxICON_QUESTION) == wxYES);
2194
2195 if (!Ok)
2196 {
2197 event.Veto();
2198 return;
2199 }
2200
2201 wxGetApp().params = savedParamSettings;
2202 }
2203
2204 if (GetParent() != NULL)
2205 GetParent()->SetFocus();
2206
2207 while (wxIsBusy())
2208 wxEndBusyCursor();
2209
2210 Show(false);
2211 SetReturnCode(0); // added so BoundsChecker would not report use of uninitialized variable
2212
2213 this->Destroy();
2214 } // CparameterDlg::OnCloseWindow()
2215
2216
2217 void CparameterDlg::OnButton( wxCommandEvent &event )
2218 {
2219 wxWindow *win = (wxWindow*) event.GetEventObject();
2220 OnCommand( *win, event );
2221 }
2222
2223
2224 void CparameterDlg::OnCommand(wxWindow& win, wxCommandEvent& WXUNUSED(event))
2225 {
2226 wxString widgetName;
2227
2228 widgetName = win.GetName();
2229
2230 if (!widgetPtrsSet)
2231 return;
2232
2233 if (widgetName == pParamSaveBtn->GetName())
2234 {
2235 if (Save())
2236 {
2237 wxString tStr;
2238 tStr = wxT("Database parameters have been saved.");
2239 if (GetParent() != NULL) // The parameter dialog was not called during startup due to a missing cfg file
2240 tStr += wxT("\nNew parameters will take effect the next time the program is started.");
2241 wxMessageBox(tStr,wxT("Notice..."),wxOK | wxICON_INFORMATION);
2242 saved = true;
2243 Close();
2244 }
2245 return;
2246 }
2247
2248 if (widgetName == pParamCancelBtn->GetName())
2249 {
2250 Close();
2251 return;
2252 }
2253 } // CparameterDlg::OnCommand()
2254
2255
2256 bool CparameterDlg::PutData()
2257 {
2258 // Fill the data source list box
2259 FillDataSourceList();
2260
2261 // Fill in the fields from the params object
2262 if (wxGetApp().params.ODBCSource && wxStrlen(wxGetApp().params.ODBCSource))
2263 {
2264 int index = pParamODBCSourceList->FindString(wxGetApp().params.ODBCSource);
2265 if (index != wxNOT_FOUND)
2266 pParamODBCSourceList->SetSelection(index);
2267 }
2268 pParamUserNameTxt->SetValue(wxGetApp().params.UserName);
2269 pParamPasswordTxt->SetValue(wxGetApp().params.Password);
2270 pParamDirPathTxt->SetValue(wxGetApp().params.DirPath);
2271 return true;
2272 } // CparameterDlg::PutData()
2273
2274
2275 bool CparameterDlg::GetData()
2276 {
2277 wxString tStr;
2278 if (pParamODBCSourceList->GetStringSelection() != wxEmptyString)
2279 {
2280 tStr = pParamODBCSourceList->GetStringSelection();
2281 if (tStr.Length() > ((int)(sizeof(wxGetApp().params.ODBCSource) / sizeof(wxChar))-1))
2282 {
2283 wxString errmsg;
2284 errmsg.Printf(wxT("ODBC Data source name is longer than the data structure to hold it.\n'Cparameter.ODBCSource' must have a larger character array\nto handle a data source with this long of a name\n\nThe data source currently selected is %d characters long."), tStr.Length());
2285 wxMessageBox(errmsg, wxT("Internal program error..."), wxOK | wxICON_EXCLAMATION);
2286 return false;
2287 }
2288 wxStrcpy(wxGetApp().params.ODBCSource, tStr);
2289 }
2290 else
2291 return false;
2292
2293 tStr = pParamUserNameTxt->GetValue();
2294 if (tStr.Length() > ((int)(sizeof(wxGetApp().params.UserName) / sizeof(wxChar))-1))
2295 {
2296 wxString errmsg;
2297 errmsg.Printf(wxT("User name is longer than the data structure to hold it.\n'Cparameter.UserName' must have a larger character array\nto handle a data source with this long of a name\n\nThe user name currently specified is %d characters long."), tStr.Length());
2298 wxMessageBox(errmsg, wxT("Internal program error..."), wxOK | wxICON_EXCLAMATION);
2299 return false;
2300 }
2301 wxStrcpy(wxGetApp().params.UserName, tStr);
2302
2303 tStr = pParamPasswordTxt->GetValue();
2304 if (tStr.Length() > ((int)(sizeof(wxGetApp().params.Password) / sizeof(wxChar))-1))
2305 {
2306 wxString errmsg;
2307 errmsg.Printf(wxT("Password is longer than the data structure to hold it.\n'Cparameter.Password' must have a larger character array\nto handle a data source with this long of a name\n\nThe password currently specified is %d characters long."), tStr.Length());
2308 wxMessageBox(errmsg, wxT("Internal program error..."), wxOK | wxICON_EXCLAMATION);
2309 return false;
2310 }
2311 wxStrcpy(wxGetApp().params.Password,tStr);
2312
2313 tStr = pParamDirPathTxt->GetValue();
2314 tStr.Replace(wxT("\\"),wxT("/"));
2315 if (tStr.Length() > ((int)(sizeof(wxGetApp().params.DirPath) / sizeof(wxChar))-1))
2316 {
2317 wxString errmsg;
2318 errmsg.Printf(wxT("DirPath is longer than the data structure to hold it.\n'Cparameter.DirPath' must have a larger character array\nto handle a data source with this long of a name\n\nThe password currently specified is %d characters long."), tStr.Length());
2319 wxMessageBox(errmsg, wxT("Internal program error..."), wxOK | wxICON_EXCLAMATION);
2320 return false;
2321 }
2322 wxStrcpy(wxGetApp().params.DirPath,tStr);
2323 return true;
2324 } // CparameterDlg::GetData()
2325
2326
2327 bool CparameterDlg::Save()
2328 {
2329 // Copy the current params in case user cancels changing
2330 // the params, so that we can reset them.
2331 if (!GetData())
2332 {
2333 wxGetApp().params = savedParamSettings;
2334 return false;
2335 }
2336
2337 wxGetApp().WriteParamFile(wxGetApp().params);
2338
2339 return true;
2340 } // CparameterDlg::Save()
2341
2342
2343 void CparameterDlg::FillDataSourceList()
2344 {
2345 wxChar Dsn[SQL_MAX_DSN_LENGTH+1];
2346 wxChar DsDesc[254+1];
2347 wxSortedArrayString strArr;
2348
2349 while (wxDbGetDataSource(wxGetApp().DbConnectInf->GetHenv(), Dsn,
2350 SQL_MAX_DSN_LENGTH, DsDesc, 254))
2351 {
2352 strArr.Add(Dsn);
2353 }
2354
2355 for (size_t i=0; i < strArr.GetCount(); i++)
2356 {
2357 pParamODBCSourceList->Append(strArr[i].c_str());
2358 }
2359
2360 } // CparameterDlg::FillDataSourceList()
2361
2362
2363 BEGIN_EVENT_TABLE(CqueryDlg, wxDialog)
2364 EVT_BUTTON(wxID_ANY, CqueryDlg::OnButton)
2365 EVT_CLOSE(CqueryDlg::OnCloseWindow)
2366 END_EVENT_TABLE()
2367
2368
2369 // CqueryDlg() constructor
2370 CqueryDlg::CqueryDlg(wxWindow *parent, wxDb *pDb, wxChar *tblName[],
2371 const wxString &pWhereArg) :
2372 wxDialog (parent, QUERY_DIALOG, wxT("Query"), wxDefaultPosition, wxSize(480, 360))
2373 {
2374 wxBeginBusyCursor();
2375
2376 colInf = 0;
2377 dbTable = 0;
2378 masterTableName = tblName[0];
2379 widgetPtrsSet = false;
2380 pDB = pDb;
2381
2382 // Initialize the WHERE clause from the string passed in
2383 pWhere = pWhereArg; // Save a pointer to the output buffer
2384 if (pWhere.Length() > (unsigned int)DB_MAX_WHERE_CLAUSE_LEN) // Check the length of the buffer passed in
2385 {
2386 wxString s;
2387 s.Printf(wxT("Maximum where clause length exceeded.\nLength must be less than %d"), DB_MAX_WHERE_CLAUSE_LEN+1);
2388 wxMessageBox(s,wxT("Error..."),wxOK | wxICON_EXCLAMATION);
2389 Close();
2390 return;
2391 }
2392
2393 pQueryCol1Msg = new wxStaticText(this, QUERY_DIALOG_COL_MSG, wxT("Column 1:"), wxPoint( 10, 10), wxSize( 69, 16), 0, wxT("QueryCol1Msg"));
2394 pQueryCol1Choice = new wxChoice(this, QUERY_DIALOG_COL_CHOICE, wxPoint( 10, 27), wxSize(250, 27), 0, 0, 0, wxDefaultValidator, wxT("QueryCol1Choice"));
2395 pQueryNotMsg = new wxStaticText(this, QUERY_DIALOG_NOT_MSG, wxT("NOT"), wxPoint(268, 10), wxDefaultSize, 0, wxT("QueryNotMsg"));
2396 pQueryNotCheck = new wxCheckBox(this, QUERY_DIALOG_NOT_CHECKBOX, wxEmptyString, wxPoint(275, 37), wxSize( 20, 20), 0, wxDefaultValidator, wxT("QueryNotCheck"));
2397
2398 wxString choice_strings[9];
2399 choice_strings[0] = wxT("=");
2400 choice_strings[1] = wxT("<");
2401 choice_strings[2] = wxT(">");
2402 choice_strings[3] = wxT("<=");
2403 choice_strings[4] = wxT(">=");
2404 choice_strings[5] = wxT("Begins");
2405 choice_strings[6] = wxT("Contains");
2406 choice_strings[7] = wxT("Like");
2407 choice_strings[8] = wxT("Between");
2408
2409 pQueryOperatorMsg = new wxStaticText(this, QUERY_DIALOG_OP_MSG, wxT("Operator:"), wxPoint(305, 10), wxDefaultSize, 0, wxT("QueryOperatorMsg"));
2410 pQueryOperatorChoice = new wxChoice(this, QUERY_DIALOG_OP_CHOICE, wxPoint(305, 27), wxSize( 80, 27), 9, choice_strings, 0, wxDefaultValidator, wxT("QueryOperatorChoice"));
2411 pQueryCol2Msg = new wxStaticText(this, QUERY_DIALOG_COL2_MSG, wxT("Column 2:"), wxPoint( 10, 65), wxSize( 69, 16), 0, wxT("QueryCol2Msg"));
2412 pQueryCol2Choice = new wxChoice(this, QUERY_DIALOG_COL2_CHOICE, wxPoint( 10, 82), wxSize(250, 27), 0, 0, 0, wxDefaultValidator, wxT("QueryCol2Choice"));
2413 pQuerySqlWhereMsg = new wxStaticText(this, QUERY_DIALOG_WHERE_MSG, wxT("SQL where clause:"), wxPoint( 10, 141), wxDefaultSize, 0, wxT("QuerySqlWhereMsg"));
2414 pQuerySqlWhereMtxt = new wxTextCtrl(this, QUERY_DIALOG_WHERE_TEXT, wxEmptyString, wxPoint( 10, 159), wxSize(377, 134), wxTE_MULTILINE, wxDefaultValidator, wxT("QuerySqlWhereMtxt"));
2415 pQueryAddBtn = new wxButton(this, QUERY_DIALOG_ADD, wxT("&Add"), wxPoint(406, 24), wxSize( 56, 26), 0, wxDefaultValidator, wxT("QueryAddBtn"));
2416 pQueryAndBtn = new wxButton(this, QUERY_DIALOG_AND, wxT("A&nd"), wxPoint(406, 58), wxSize( 56, 26), 0, wxDefaultValidator, wxT("QueryAndBtn"));
2417 pQueryOrBtn = new wxButton(this, QUERY_DIALOG_OR, wxT("&Or"), wxPoint(406, 92), wxSize( 56, 26), 0, wxDefaultValidator, wxT("QueryOrBtn"));
2418 pQueryLParenBtn = new wxButton(this, QUERY_DIALOG_LPAREN, wxT("("), wxPoint(406, 126), wxSize( 26, 26), 0, wxDefaultValidator, wxT("QueryLParenBtn"));
2419 pQueryRParenBtn = new wxButton(this, QUERY_DIALOG_RPAREN, wxT(")"), wxPoint(436, 126), wxSize( 26, 26), 0, wxDefaultValidator, wxT("QueryRParenBtn"));
2420 pQueryDoneBtn = new wxButton(this, QUERY_DIALOG_DONE, wxT("&Done"), wxPoint(406, 185), wxSize( 56, 26), 0, wxDefaultValidator, wxT("QueryDoneBtn"));
2421 pQueryClearBtn = new wxButton(this, QUERY_DIALOG_CLEAR, wxT("C&lear"), wxPoint(406, 218), wxSize( 56, 26), 0, wxDefaultValidator, wxT("QueryClearBtn"));
2422 pQueryCountBtn = new wxButton(this, QUERY_DIALOG_COUNT, wxT("&Count"), wxPoint(406, 252), wxSize( 56, 26), 0, wxDefaultValidator, wxT("QueryCountBtn"));
2423 pQueryValue1Msg = new wxStaticText(this, QUERY_DIALOG_VALUE1_MSG, wxT("Value:"), wxPoint(277, 66), wxDefaultSize, 0, wxT("QueryValue1Msg"));
2424 pQueryValue1Txt = new wxTextCtrl(this, QUERY_DIALOG_VALUE1_TEXT, wxEmptyString, wxPoint(277, 83), wxSize(108, 25), 0, wxDefaultValidator, wxT("QueryValue1Txt"));
2425 pQueryValue2Msg = new wxStaticText(this, QUERY_DIALOG_VALUE2_MSG, wxT("AND"), wxPoint(238, 126), wxDefaultSize, 0, wxT("QueryValue2Msg"));
2426 pQueryValue2Txt = new wxTextCtrl(this, QUERY_DIALOG_VALUE2_TEXT, wxEmptyString, wxPoint(277, 120), wxSize(108, 25), 0, wxDefaultValidator, wxT("QueryValue2Txt"));
2427 pQueryHintGrp = new wxStaticBox(this, QUERY_DIALOG_HINT_GROUP, wxEmptyString, wxPoint( 10, 291), wxSize(377, 40), 0, wxT("QueryHintGrp"));
2428 pQueryHintMsg = new wxStaticText(this, QUERY_DIALOG_HINT_MSG, wxEmptyString, wxPoint( 16, 306), wxDefaultSize, 0, wxT("QueryHintMsg"));
2429
2430 widgetPtrsSet = true;
2431 // Initialize the dialog
2432 wxString qualName;
2433 pQueryCol2Choice->Append(wxT("VALUE -->"));
2434 colInf = pDB->GetColumns(tblName);
2435
2436 if (!colInf)
2437 {
2438 wxEndBusyCursor();
2439 wxString tStr;
2440 tStr = wxT("ODBC error during GetColumns()\n\n");
2441 wxMessageBox(wxDbLogExtendedErrorMsg(tStr.c_str(),wxGetApp().Contact->GetDb(),__TFILE__,__LINE__),
2442 wxT("ODBC Error..."),wxOK | wxICON_EXCLAMATION);
2443 return;
2444 }
2445
2446 int i;
2447 for (i = 0; colInf[i].colName && wxStrlen(colInf[i].colName); i++)
2448 {
2449 // If there is more than one table being queried, qualify
2450 // the column names with the table name prefix.
2451 if (tblName[1] && wxStrlen(tblName[1]))
2452 {
2453 qualName.Printf(wxT("%s.%s"), colInf[i].tableName, colInf[i].colName);
2454 pQueryCol1Choice->Append(qualName);
2455 pQueryCol2Choice->Append(qualName);
2456 }
2457 else // Single table query, append just the column names
2458 {
2459 pQueryCol1Choice->Append(colInf[i].colName);
2460 pQueryCol2Choice->Append(colInf[i].colName);
2461 }
2462 }
2463
2464 pQueryCol1Choice->SetSelection(0);
2465 pQueryCol2Choice->SetSelection(0);
2466 pQueryOperatorChoice->SetSelection(0);
2467
2468 pQueryValue2Msg->Show(false);
2469 pQueryValue2Txt->Show(false);
2470
2471 pQueryHintMsg->SetLabel(langQRY_EQ);
2472
2473 pQuerySqlWhereMtxt->SetValue(pWhere.c_str());
2474
2475 wxEndBusyCursor();
2476
2477 // Display the dialog window
2478 Centre(wxBOTH);
2479 ShowModal();
2480 } // CqueryDlg() constructor
2481
2482
2483 CqueryDlg::~CqueryDlg()
2484 {
2485 } // CqueryDlg::~CqueryDlg() destructor
2486
2487
2488 void CqueryDlg::OnButton(wxCommandEvent &event)
2489 {
2490 wxWindow *win = (wxWindow*) event.GetEventObject();
2491 OnCommand( *win, event );
2492 } // CqueryDlg::OnButton()
2493
2494
2495 void CqueryDlg::OnCommand(wxWindow& win, wxCommandEvent& WXUNUSED(event))
2496 {
2497 // Widget pointers won't be set when the dialog is constructed.
2498 // Control is passed through this function once for each widget on
2499 // a dialog as the dialog is constructed.
2500 if (!widgetPtrsSet)
2501 return;
2502
2503 wxString widgetName = win.GetName();
2504
2505 // Operator choice box
2506 if (widgetName == pQueryOperatorChoice->GetName())
2507 {
2508 // Set the help text
2509 switch((qryOp) pQueryOperatorChoice->GetSelection())
2510 {
2511 case qryOpEQ:
2512 pQueryHintMsg->SetLabel(langQRY_EQ);
2513 break;
2514 case qryOpLT:
2515 pQueryHintMsg->SetLabel(langQRY_LT);
2516 break;
2517 case qryOpGT:
2518 pQueryHintMsg->SetLabel(langQRY_GT);
2519 break;
2520 case qryOpLE:
2521 pQueryHintMsg->SetLabel(langQRY_LE);
2522 break;
2523 case qryOpGE:
2524 pQueryHintMsg->SetLabel(langQRY_GE);
2525 break;
2526 case qryOpBEGINS:
2527 pQueryHintMsg->SetLabel(langQRY_BEGINS);
2528 break;
2529 case qryOpCONTAINS:
2530 pQueryHintMsg->SetLabel(langQRY_CONTAINS);
2531 break;
2532 case qryOpLIKE:
2533 pQueryHintMsg->SetLabel(langQRY_LIKE);
2534 break;
2535 case qryOpBETWEEN:
2536 pQueryHintMsg->SetLabel(langQRY_BETWEEN);
2537 break;
2538 }
2539
2540 // Hide the value2 widget
2541 pQueryValue2Msg->Show(false); // BETWEEN will show this widget
2542 pQueryValue2Txt->Show(false); // BETWEEN will show this widget
2543
2544 // Disable the NOT operator for <, <=, >, >=
2545 switch((qryOp) pQueryOperatorChoice->GetSelection())
2546 {
2547 case qryOpLT:
2548 case qryOpGT:
2549 case qryOpLE:
2550 case qryOpGE:
2551 pQueryNotCheck->SetValue(0);
2552 pQueryNotCheck->Enable(false);
2553 break;
2554 default:
2555 pQueryNotCheck->Enable(true);
2556 break;
2557 }
2558
2559 // Manipulate the dialog to handle the selected operator
2560 switch((qryOp) pQueryOperatorChoice->GetSelection())
2561 {
2562 case qryOpEQ:
2563 case qryOpLT:
2564 case qryOpGT:
2565 case qryOpLE:
2566 case qryOpGE:
2567 pQueryCol2Choice->Enable(true);
2568 if (pQueryCol2Choice->GetSelection()) // Column name is highlighted
2569 {
2570 pQueryValue1Msg->Show(false);
2571 pQueryValue1Txt->Show(false);
2572 }
2573 else // "Value" is highlighted
2574 {
2575 pQueryValue1Msg->Show(true);
2576 pQueryValue1Txt->Show(true);
2577 pQueryValue1Txt->SetFocus();
2578 }
2579 break;
2580 case qryOpBEGINS:
2581 case qryOpCONTAINS:
2582 case qryOpLIKE:
2583 pQueryCol2Choice->SetSelection(0);
2584 pQueryCol2Choice->Enable(false);
2585 pQueryValue1Msg->Show(true);
2586 pQueryValue1Txt->Show(true);
2587 pQueryValue1Txt->SetFocus();
2588 break;
2589 case qryOpBETWEEN:
2590 pQueryCol2Choice->SetSelection(0);
2591 pQueryCol2Choice->Enable(false);
2592 pQueryValue2Msg->Show(true);
2593 pQueryValue2Txt->Show(true);
2594 pQueryValue1Msg->Show(true);
2595 pQueryValue1Txt->Show(true);
2596 pQueryValue1Txt->SetFocus();
2597 break;
2598 }
2599
2600 return;
2601
2602 } // Operator choice box
2603
2604 // Column 2 choice
2605 if (widgetName == pQueryCol2Choice->GetName())
2606 {
2607 if (pQueryCol2Choice->GetSelection()) // Column name is highlighted
2608 {
2609 pQueryValue1Msg->Show(false);
2610 pQueryValue1Txt->Show(false);
2611 }
2612 else // "Value" is highlighted
2613 {
2614 pQueryValue1Msg->Show(true);
2615 pQueryValue1Txt->Show(true);
2616 pQueryValue1Txt->SetFocus();
2617 }
2618 return;
2619 } // Column 2 choice
2620
2621 // Add button
2622 if (widgetName == pQueryAddBtn->GetName())
2623 {
2624 ProcessAddBtn();
2625 return;
2626 } // Add button
2627
2628 // And button
2629 if (widgetName == pQueryAndBtn->GetName())
2630 {
2631 AppendToWhere(wxT(" AND\n"));
2632 return;
2633 } // And button
2634
2635 // Or button
2636 if (widgetName == pQueryOrBtn->GetName())
2637 {
2638 AppendToWhere(wxT(" OR\n"));
2639 return;
2640 } // Or button
2641
2642 // Left Paren button
2643 if (widgetName == pQueryLParenBtn->GetName())
2644 {
2645 AppendToWhere(wxT("("));
2646 return;
2647 } // Left Paren button
2648
2649 // Right paren button
2650 if (widgetName == pQueryRParenBtn->GetName())
2651 {
2652 AppendToWhere(wxT(")"));
2653 return;
2654 } // Right Paren button
2655
2656 // Done button
2657 if (widgetName == pQueryDoneBtn->GetName())
2658 {
2659 // Be sure the where clause will not overflow the output buffer
2660 if (wxStrlen(pQuerySqlWhereMtxt->GetValue()) > (unsigned int)DB_MAX_WHERE_CLAUSE_LEN)
2661 {
2662 wxString s;
2663 s.Printf(wxT("Maximum where clause length exceeded.\nLength must be less than %d"), DB_MAX_WHERE_CLAUSE_LEN+1);
2664 wxMessageBox(s,wxT("Error..."),wxOK | wxICON_EXCLAMATION);
2665 return;
2666 }
2667 // Validate the where clause for things such as matching parens
2668 if (!ValidateWhereClause())
2669 return;
2670 // Copy the where clause to the output buffer and exit
2671 pWhere = pQuerySqlWhereMtxt->GetValue();
2672 Close();
2673 return;
2674 } // Done button
2675
2676 // Clear button
2677 if (widgetName == pQueryClearBtn->GetName())
2678 {
2679 bool Ok = (wxMessageBox(wxT("Are you sure you wish to clear the Query?"), wxT("Confirm"), wxYES_NO|wxICON_QUESTION) == wxYES);
2680
2681 if (Ok)
2682 pQuerySqlWhereMtxt->SetValue(wxEmptyString);
2683
2684 return;
2685 } // Clear button
2686
2687 // Count button
2688 if (widgetName == pQueryCountBtn->GetName())
2689 {
2690 wxBeginBusyCursor();
2691 ProcessCountBtn();
2692 wxEndBusyCursor();
2693 return;
2694 } // Count button
2695
2696 } // CqueryDlg::OnCommand
2697
2698
2699 void CqueryDlg::OnCloseWindow(wxCloseEvent& WXUNUSED(event))
2700 {
2701 // Clean up
2702 wxDELETEA(colInf);
2703
2704 wxDELETE(dbTable);
2705
2706 GetParent()->SetFocus();
2707 while (wxIsBusy())
2708 wxEndBusyCursor();
2709
2710 Show(false);
2711 SetReturnCode(1); // added so BoundsChecker would not report use of uninitialized variable
2712
2713 this->Destroy();
2714 } // CqueryDlg::OnCloseWindow()
2715
2716
2717 void CqueryDlg::AppendToWhere(wxChar *s)
2718 {
2719 wxString whereStr = pQuerySqlWhereMtxt->GetValue();
2720 whereStr += s;
2721 pQuerySqlWhereMtxt->SetValue(whereStr);
2722 } // CqueryDlg::AppendToWhere()
2723
2724
2725 void CqueryDlg::ProcessAddBtn()
2726 {
2727 qryOp oper = (qryOp) pQueryOperatorChoice->GetSelection();
2728
2729 // Verify that eveything is filled in correctly
2730 if (pQueryCol2Choice->GetSelection() == 0) // "Value" is selected
2731 {
2732 // Verify that value 1 is filled in
2733 if (wxStrlen(pQueryValue1Txt->GetValue()) == 0)
2734 {
2735 wxBell();
2736 pQueryValue1Txt->SetFocus();
2737 return;
2738 }
2739 // For the BETWEEN operator, value 2 must be filled in as well
2740 if (oper == qryOpBETWEEN &&
2741 wxStrlen(pQueryValue2Txt->GetValue()) == 0)
2742 {
2743 wxBell();
2744 pQueryValue2Txt->SetFocus();
2745 return;
2746 }
2747 }
2748
2749 // Build the expression and append it to the where clause window
2750 wxString s = pQueryCol1Choice->GetStringSelection();
2751
2752 if (pQueryNotCheck->GetValue() && (oper != qryOpEQ))
2753 s += wxT(" NOT");
2754
2755 switch(oper)
2756 {
2757 case qryOpEQ:
2758 if (pQueryNotCheck->GetValue()) // NOT box is checked
2759 s += wxT(" <>");
2760 else
2761 s += wxT(" =");
2762 break;
2763 case qryOpLT:
2764 s += wxT(" <");
2765 break;
2766 case qryOpGT:
2767 s += wxT(" >");
2768 break;
2769 case qryOpLE:
2770 s += wxT(" <=");
2771 break;
2772 case qryOpGE:
2773 s += wxT(" >=");
2774 break;
2775 case qryOpBEGINS:
2776 case qryOpCONTAINS:
2777 case qryOpLIKE:
2778 s += wxT(" LIKE");
2779 break;
2780 case qryOpBETWEEN:
2781 s += wxT(" BETWEEN");
2782 break;
2783 }
2784
2785 s += wxT(" ");
2786
2787 int col1Idx = pQueryCol1Choice->GetSelection();
2788
2789 bool quote = false;
2790 if (colInf[col1Idx].sqlDataType == SQL_VARCHAR ||
2791 oper == qryOpBEGINS ||
2792 oper == qryOpCONTAINS ||
2793 oper == qryOpLIKE)
2794 quote = true;
2795
2796 if (pQueryCol2Choice->GetSelection()) // Column name
2797 s += pQueryCol2Choice->GetStringSelection();
2798 else // Column 2 is a "value"
2799 {
2800 if (quote)
2801 s += wxT("'");
2802 if (oper == qryOpCONTAINS)
2803 s += wxT("%");
2804 s += pQueryValue1Txt->GetValue();
2805 if (oper == qryOpCONTAINS || oper == qryOpBEGINS)
2806 s += wxT("%");
2807 if (quote)
2808 s += wxT("'");
2809 }
2810
2811 if (oper == qryOpBETWEEN)
2812 {
2813 s += wxT(" AND ");
2814 if (quote)
2815 s += wxT("'");
2816 s += pQueryValue2Txt->GetValue();
2817 if (quote)
2818 s += wxT("'");
2819 }
2820
2821 AppendToWhere((wxChar*) (const wxChar*) s);
2822
2823 } // CqueryDlg::ProcessAddBtn()
2824
2825
2826 void CqueryDlg::ProcessCountBtn()
2827 {
2828 if (!ValidateWhereClause())
2829 return;
2830
2831 if (!dbTable) // wxDbTable object needs to be created and opened
2832 {
2833 dbTable = new wxDbTable(pDB, masterTableName, 0, (const wxString &)wxEmptyString,
2834 !wxDB_QUERY_ONLY,
2835 wxGetApp().DbConnectInf->GetDefaultDir());
2836 if (!dbTable)
2837 {
2838 wxMessageBox(wxT("Memory allocation failed creating a wxDbTable object."),wxT("Error..."),wxOK | wxICON_EXCLAMATION);
2839 return;
2840 }
2841 if (!dbTable->Open())
2842 {
2843 wxString tStr;
2844 tStr = wxT("ODBC error during Open()\n\n");
2845 wxMessageBox(wxDbLogExtendedErrorMsg(tStr.c_str(),wxGetApp().Contact->GetDb(),__TFILE__,__LINE__),
2846 wxT("ODBC Error..."),wxOK | wxICON_EXCLAMATION);
2847 return;
2848 }
2849 }
2850
2851 // Count() with WHERE clause
2852 wxString whereStr;
2853
2854 whereStr = pQuerySqlWhereMtxt->GetValue();
2855 dbTable->SetWhereClause(whereStr.c_str());
2856
2857 ULONG whereCnt = dbTable->Count();
2858
2859 // Count() of all records in the table
2860 dbTable->SetWhereClause(wxEmptyString);
2861 ULONG totalCnt = dbTable->Count();
2862
2863 if (whereCnt > 0 || totalCnt == 0)
2864 {
2865 wxString tStr;
2866 tStr.Printf(wxT("%lu of %lu records match the query criteria."),whereCnt,totalCnt);
2867 wxMessageBox(tStr,wxT("Notice..."),wxOK | wxICON_INFORMATION);
2868 }
2869 else
2870 {
2871 wxString tStr;
2872 tStr.Printf(wxT("%lu of %lu records match the query criteria.\n\nEither the criteria entered produced a result set\nwith no records, or there was a syntactical error\nin the clause you entered.\n\nPress the details button to see if any database errors were reported."),whereCnt,totalCnt);
2873 wxMessageBox(tStr,wxT("Notice..."),wxOK | wxICON_INFORMATION);
2874 }
2875
2876 // After a wxMessageBox, the focus does not necessarily return to the
2877 // window which was the focus when the message box popped up, so return
2878 // focus to the Query dialog for certain
2879 SetFocus();
2880
2881 } // CqueryDlg::ProcessCountBtn()
2882
2883
2884 bool CqueryDlg::ValidateWhereClause()
2885 {
2886 wxString where = pQuerySqlWhereMtxt->GetValue();
2887
2888 if (where.Freq(wxT('(')) != where.Freq(wxT(')')))
2889 {
2890 wxMessageBox(wxT("There are mismatched parenthesis in the constructed where clause"),wxT("Error..."),wxOK | wxICON_EXCLAMATION);
2891 return(false);
2892 }
2893 // After a wxMessageBox, the focus does not necessarily return to the
2894 // window which was the focus when the message box popped up, so return
2895 // focus to the Query dialog for certain
2896 SetFocus();
2897
2898 return(true);
2899
2900 } // CqueryDlg::ValidateWhereClause()
2901
2902 #ifdef wxODBC_BLOB_SUPPORT
2903
2904 BEGIN_EVENT_TABLE(CimageDlg, wxDialog)
2905 EVT_CLOSE(CimageDlg::OnCloseWindow)
2906 END_EVENT_TABLE()
2907
2908 CimageDlg::CimageDlg(wxWindow *parent, wxChar *pImageData, off_t iSize)
2909 : wxDialog(parent, IMAGE_DIALOG, wxT("BLOB Image"), wxDefaultPosition, wxDefaultSize),
2910 m_pDisplayBmp(NULL),
2911 m_pBmp(NULL),
2912 m_pImage(NULL)
2913 {
2914 wxMemoryInputStream inStream(pImageData, iSize);
2915
2916 if(inStream.IsOk())
2917 {
2918 m_pImage = new wxImage(inStream, wxBITMAP_TYPE_ANY);
2919
2920 if(m_pImage->Ok())
2921 {
2922 m_pBmp = new wxBitmap(*m_pImage);
2923 m_pDisplayBmp = new wxStaticBitmap(this, IMAGE_DIALOG_STATIC_BMP, *m_pBmp, wxPoint(5,5), wxDefaultSize);
2924
2925 SetSize(m_pBmp->GetWidth() + 10, m_pBmp->GetHeight() + 30);
2926 }
2927 }
2928 }
2929
2930 CimageDlg::~CimageDlg()
2931 {
2932 if(m_pImage)
2933 delete m_pImage;
2934
2935 if(m_pBmp)
2936 delete m_pBmp;
2937
2938 if(m_pDisplayBmp)
2939 delete m_pDisplayBmp;
2940 }
2941
2942 void CimageDlg::OnCloseWindow(wxCloseEvent& WXUNUSED(event))
2943 {
2944 GetParent()->SetFocus();
2945
2946 Show(false);
2947
2948 this->Destroy();
2949 }
2950
2951 #endif
2952
2953 void DisplayDbDiagnostics(wxDb *pDb)
2954 {
2955 wxString s, t;
2956 bool comma;
2957
2958 s = wxT("Diagnostics Output\n");
2959 s += langDBINF_DB_NAME;
2960 s += pDb->dbInf.dbmsName;
2961 s += wxT("\n");
2962
2963 s += langDBINF_DB_VER;
2964 s += pDb->dbInf.dbmsVer;
2965 s += wxT("\n");
2966
2967 s += langDBINF_DRIVER_NAME;
2968 s += pDb->dbInf.driverName;
2969 s += wxT("\n");
2970
2971 s += langDBINF_DRIVER_ODBC_VER;
2972 s += pDb->dbInf.odbcVer;
2973 s += wxT("\n");
2974
2975 s += langDBINF_DRIVER_MGR_ODBC_VER;
2976 s += pDb->dbInf.drvMgrOdbcVer;
2977 s += wxT("\n");
2978
2979 s += langDBINF_DRIVER_VER;
2980 s += pDb->dbInf.driverVer;
2981 s += wxT("\n");
2982
2983 s += langDBINF_SERVER_NAME;
2984 s += pDb->dbInf.serverName;
2985 s += wxT("\n");
2986
2987 s += langDBINF_FILENAME;
2988 s += pDb->dbInf.databaseName;
2989 s += wxT("\n");
2990
2991 s += langDBINF_OUTER_JOINS;
2992 s += pDb->dbInf.outerJoins;
2993 s += wxT("\n");
2994
2995 s += langDBINF_STORED_PROC;
2996 s += pDb->dbInf.procedureSupport;
2997 s += wxT("\n");
2998
2999 if (pDb->dbInf.maxConnections)
3000 t.sprintf(wxT("%s%d\n"), langDBINF_MAX_HDBC, pDb->dbInf.maxConnections);
3001 else
3002 t.sprintf(wxT("%s%s\n"), langDBINF_MAX_HDBC, langDBINF_UNLIMITED);
3003 s += t;
3004
3005 if (pDb->dbInf.maxStmts)
3006 t.sprintf(wxT("%s%d\n"), langDBINF_MAX_HSTMT, pDb->dbInf.maxStmts);
3007 else
3008 t.sprintf(wxT("%s%s\n"), langDBINF_MAX_HSTMT, langDBINF_UNLIMITED);
3009 s += t;
3010
3011 s += langDBINF_API_LVL;
3012 switch(pDb->dbInf.apiConfLvl)
3013 {
3014 case SQL_OAC_NONE: s += langDBINF_NONE; break;
3015 case SQL_OAC_LEVEL1: s += langDBINF_LEVEL1; break;
3016 case SQL_OAC_LEVEL2: s += langDBINF_LEVEL2; break;
3017 }
3018 s += wxT("\n");
3019
3020 s += langDBINF_CLI_LVL;
3021 switch(pDb->dbInf.cliConfLvl)
3022 {
3023 case SQL_OSCC_NOT_COMPLIANT: s += langDBINF_NOT_COMPLIANT; break;
3024 case SQL_OSCC_COMPLIANT: s += langDBINF_COMPLIANT; break;
3025 }
3026 s += wxT("\n");
3027
3028 s += langDBINF_SQL_LVL;
3029 switch(pDb->dbInf.sqlConfLvl)
3030 {
3031 case SQL_OSC_MINIMUM: s += langDBINF_MIN_GRAMMAR; break;
3032 case SQL_OSC_CORE: s += langDBINF_CORE_GRAMMAR; break;
3033 case SQL_OSC_EXTENDED: s += langDBINF_EXT_GRAMMAR; break;
3034 }
3035 s += wxT("\n");
3036
3037 s += langDBINF_COMMIT_BEHAVIOR;
3038 switch(pDb->dbInf.cursorCommitBehavior)
3039 {
3040 case SQL_CB_DELETE: s += langDBINF_DELETE_CURSORS; break;
3041 case SQL_CB_CLOSE: s += langDBINF_CLOSE_CURSORS; break;
3042 case SQL_CB_PRESERVE: s += langDBINF_PRESERVE_CURSORS; break;
3043 }
3044 s += wxT("\n");
3045
3046 s += langDBINF_ROLLBACK_BEHAVIOR;
3047 switch(pDb->dbInf.cursorRollbackBehavior)
3048 {
3049 case SQL_CB_DELETE: s += langDBINF_DELETE_CURSORS; break;
3050 case SQL_CB_CLOSE: s += langDBINF_CLOSE_CURSORS; break;
3051 case SQL_CB_PRESERVE: s += langDBINF_PRESERVE_CURSORS; break;
3052 }
3053 s += wxT("\n");
3054
3055 s += langDBINF_SUPP_NOT_NULL;
3056 switch(pDb->dbInf.supportNotNullClause)
3057 {
3058 case SQL_NNC_NULL: s += langNO; break;
3059 case SQL_NNC_NON_NULL: s += langYES; break;
3060 }
3061 s += wxT("\n");
3062
3063 s += langDBINF_SUPP_IEF;
3064 s += pDb->dbInf.supportIEF;
3065 s += wxT("\n");
3066
3067 // DEFAULT setting for "Transaction Isolation Level"
3068 s += langDBINF_TXN_ISOLATION;
3069 switch(pDb->dbInf.txnIsolation)
3070 {
3071 case SQL_TXN_READ_UNCOMMITTED: s += langDBINF_READ_UNCOMMITTED; break;
3072 case SQL_TXN_READ_COMMITTED: s += langDBINF_READ_COMMITTED; break;
3073 case SQL_TXN_REPEATABLE_READ: s += langDBINF_REPEATABLE_READ; break;
3074 case SQL_TXN_SERIALIZABLE: s += langDBINF_SERIALIZABLE; break;
3075 #ifdef ODBC_V20
3076 case SQL_TXN_VERSIONING: s += langDBINF_VERSIONING; break;
3077 #endif
3078 }
3079 s += wxT("\n");
3080
3081 // CURRENT setting for "Transaction Isolation Level"
3082 long txnIsoLvl;
3083 s += langDBINF_TXN_ISOLATION_CURR;
3084 if (SQLGetConnectOption(pDb->GetHDBC(),SQL_TXN_ISOLATION,&txnIsoLvl) == SQL_SUCCESS)
3085 {
3086 switch(txnIsoLvl)
3087 {
3088 case SQL_TXN_READ_UNCOMMITTED: s += langDBINF_READ_UNCOMMITTED; break;
3089 case SQL_TXN_READ_COMMITTED: s += langDBINF_READ_COMMITTED; break;
3090 case SQL_TXN_REPEATABLE_READ: s += langDBINF_REPEATABLE_READ; break;
3091 case SQL_TXN_SERIALIZABLE: s += langDBINF_SERIALIZABLE; break;
3092 #ifdef ODBC_V20
3093 case SQL_TXN_VERSIONING: s += langDBINF_VERSIONING; break;
3094 #endif
3095 }
3096 }
3097 s += wxT("\n");
3098
3099 #ifdef __VMS__
3100 #pragma message disable incboodep
3101 #endif
3102 comma = false;
3103 s += langDBINF_TXN_ISOLATION_OPTS;
3104 if (pDb->dbInf.txnIsolationOptions & SQL_TXN_READ_UNCOMMITTED)
3105 {s += langDBINF_READ_UNCOMMITTED; comma++;}
3106 if (pDb->dbInf.txnIsolationOptions & SQL_TXN_READ_COMMITTED)
3107 {if (comma++) s += wxT(", "); s += langDBINF_READ_COMMITTED;}
3108 if (pDb->dbInf.txnIsolationOptions & SQL_TXN_REPEATABLE_READ)
3109 {if (comma++) s += wxT(", "); s += langDBINF_REPEATABLE_READ;}
3110 if (pDb->dbInf.txnIsolationOptions & SQL_TXN_SERIALIZABLE)
3111 {if (comma++) s += wxT(", "); s += langDBINF_SERIALIZABLE;}
3112 #ifdef ODBC_V20
3113 if (pDb->dbInf.txnIsolationOptions & SQL_TXN_VERSIONING)
3114 {if (comma++) s += wxT(", "); s += langDBINF_VERSIONING;}
3115 #endif
3116 s += wxT("\n");
3117
3118 comma = false;
3119 s += langDBINF_FETCH_DIRS;
3120 if (pDb->dbInf.fetchDirections & SQL_FD_FETCH_NEXT)
3121 {s += langDBINF_NEXT; comma++;}
3122 if (pDb->dbInf.fetchDirections & SQL_FD_FETCH_PRIOR)
3123 {if (comma++) s += wxT(", "); s += langDBINF_PREV;}
3124 if (pDb->dbInf.fetchDirections & SQL_FD_FETCH_FIRST)
3125 {if (comma++) s += wxT(", "); s += langDBINF_FIRST;}
3126 if (pDb->dbInf.fetchDirections & SQL_FD_FETCH_LAST)
3127 {if (comma++) s += wxT(", "); s += langDBINF_LAST;}
3128 if (pDb->dbInf.fetchDirections & SQL_FD_FETCH_ABSOLUTE)
3129 {if (comma++) s += wxT(", "); s += langDBINF_ABSOLUTE;}
3130 if (pDb->dbInf.fetchDirections & SQL_FD_FETCH_RELATIVE)
3131 {if (comma++) s += wxT(", "); s += langDBINF_RELATIVE;}
3132 #ifdef ODBC_V20
3133 if (pDb->dbInf.fetchDirections & SQL_FD_FETCH_RESUME)
3134 {if (comma++) s += wxT(", "); s += langDBINF_RESUME;}
3135 #endif
3136 if (pDb->dbInf.fetchDirections & SQL_FD_FETCH_BOOKMARK)
3137 {if (comma++) s += wxT(", "); s += langDBINF_BOOKMARK;}
3138 s += wxT("\n");
3139
3140 comma = false;
3141 s += langDBINF_LOCK_TYPES;
3142 if (pDb->dbInf.lockTypes & SQL_LCK_NO_CHANGE)
3143 {s += langDBINF_NO_CHANGE; comma++;}
3144 if (pDb->dbInf.lockTypes & SQL_LCK_EXCLUSIVE)
3145 {if (comma++) s += wxT(", "); s += langDBINF_EXCLUSIVE;}
3146 if (pDb->dbInf.lockTypes & SQL_LCK_UNLOCK)
3147 {if (comma++) s += wxT(", "); s += langDBINF_UNLOCK;}
3148 s += wxT("\n");
3149
3150 comma = false;
3151 s += langDBINF_POS_OPERS;
3152 if (pDb->dbInf.posOperations & SQL_POS_POSITION)
3153 {s += langDBINF_POSITION; comma++;}
3154 if (pDb->dbInf.posOperations & SQL_POS_REFRESH)
3155 {if (comma++) s += wxT(", "); s += langDBINF_REFRESH;}
3156 if (pDb->dbInf.posOperations & SQL_POS_UPDATE)
3157 {if (comma++) s += wxT(", "); s += langDBINF_UPD;}
3158 if (pDb->dbInf.posOperations & SQL_POS_DELETE)
3159 {if (comma++) s += wxT(", "); s += langDBINF_DEL;}
3160 if (pDb->dbInf.posOperations & SQL_POS_ADD)
3161 {if (comma++) s += wxT(", "); s += langDBINF_ADD;}
3162 s += wxT("\n");
3163
3164 comma = false;
3165 s += langDBINF_POS_STMTS;
3166 if (pDb->dbInf.posStmts & SQL_PS_POSITIONED_DELETE)
3167 {s += langDBINF_POS_DEL; comma++;}
3168 if (pDb->dbInf.posStmts & SQL_PS_POSITIONED_UPDATE)
3169 {if (comma++) s += wxT(", "); s += langDBINF_POS_UPD;}
3170 if (pDb->dbInf.posStmts & SQL_PS_SELECT_FOR_UPDATE)
3171 {if (comma++) s += wxT(", "); s += langDBINF_SELECT_FOR_UPD;}
3172 s += wxT("\n");
3173
3174 comma = false;
3175 s += langDBINF_SCROLL_CONCURR;
3176 if (pDb->dbInf.scrollConcurrency & SQL_SCCO_READ_ONLY)
3177 {s += langDBINF_READ_ONLY; comma++;}
3178 if (pDb->dbInf.scrollConcurrency & SQL_SCCO_LOCK)
3179 {if (comma++) s += wxT(", "); s += langDBINF_LOCK;}
3180 if (pDb->dbInf.scrollConcurrency & SQL_SCCO_OPT_ROWVER)
3181 {if (comma++) s += wxT(", "); s += langDBINF_OPT_ROWVER;}
3182 if (pDb->dbInf.scrollConcurrency & SQL_SCCO_OPT_VALUES)
3183 {if (comma++) s += wxT(", "); s += langDBINF_OPT_VALUES;}
3184 s += wxT("\n");
3185
3186 comma = false;
3187 s += langDBINF_SCROLL_OPTS;
3188 if (pDb->dbInf.scrollOptions & SQL_SO_FORWARD_ONLY)
3189 {s += langDBINF_FWD_ONLY; comma++;}
3190 if (pDb->dbInf.scrollOptions & SQL_SO_STATIC)
3191 {if (comma++) s += wxT(", "); s += langDBINF_STATIC;}
3192 if (pDb->dbInf.scrollOptions & SQL_SO_KEYSET_DRIVEN)
3193 {if (comma++) s += wxT(", "); s += langDBINF_KEYSET_DRIVEN;}
3194 if (pDb->dbInf.scrollOptions & SQL_SO_DYNAMIC)
3195 {if (comma++) s += wxT(", "); s += langDBINF_DYNAMIC;}
3196 if (pDb->dbInf.scrollOptions & SQL_SO_MIXED)
3197 {if (comma++) s += wxT(", "); s += langDBINF_MIXED;}
3198 s += wxT("\n");
3199
3200 comma = false;
3201 s += langDBINF_STATIC_SENS;
3202 if (pDb->dbInf.staticSensitivity & SQL_SS_ADDITIONS)
3203 {s += langDBINF_ADDITIONS; comma++;}
3204 if (pDb->dbInf.staticSensitivity & SQL_SS_DELETIONS)
3205 {if (comma++) s += wxT(", "); s += langDBINF_DELETIONS;}
3206 if (pDb->dbInf.staticSensitivity & SQL_SS_UPDATES)
3207 {if (comma++) s += wxT(", "); s += langDBINF_UPDATES;}
3208 s += wxT("\n");
3209 #ifdef __VMS__
3210 #pragma message enable incboodep
3211 #endif
3212
3213
3214 s += langDBINF_TXN_CAPABLE;
3215 switch(pDb->dbInf.txnCapable)
3216 {
3217 case SQL_TC_NONE: s += langNO; break;
3218 case SQL_TC_DML: s += langDBINF_DML_ONLY; break;
3219 case SQL_TC_DDL_COMMIT: s += langDBINF_DDL_COMMIT; break;
3220 case SQL_TC_DDL_IGNORE: s += langDBINF_DDL_IGNORE; break;
3221 case SQL_TC_ALL: s += langDBINF_DDL_AND_DML; break;
3222 }
3223 s += wxT("\n");
3224
3225 t.sprintf(wxT("%s%lu\n"), langDBINF_LOGIN_TIMEOUT, pDb->dbInf.loginTimeout);
3226 s += t;
3227
3228 // Oracle specific information
3229 if (pDb->Dbms() == dbmsORACLE)
3230 {
3231 s += wxT("\n");
3232 s += langDBINF_ORACLE_BANNER;
3233 s += wxT("\n");
3234
3235 // Oracle cache hit ratio
3236 SDWORD cb;
3237 ULONG dbBlockGets;
3238 pDb->ExecSql(wxT("SELECT VALUE FROM V$SYSSTAT WHERE NAME = 'db block gets'"));
3239 pDb->GetNext();
3240 if (pDb->GetData(1, SQL_C_ULONG, &dbBlockGets, 0, &cb))
3241 {
3242 t.sprintf(wxT("%s: %lu\n"), langDBINF_DB_BLOCK_GETS, dbBlockGets);
3243 s += t;
3244 }
3245
3246 ULONG consistentGets;
3247 pDb->ExecSql(wxT("SELECT VALUE FROM V$SYSSTAT WHERE NAME = 'consistent gets'"));
3248 pDb->GetNext();
3249 if (pDb->GetData(1, SQL_C_ULONG, &consistentGets, 0, &cb))
3250 {
3251 t.sprintf(wxT("%s: %lu\n"), langDBINF_CONSISTENT_GETS, consistentGets);
3252 s += t;
3253 }
3254
3255 ULONG physReads;
3256 pDb->ExecSql(wxT("SELECT VALUE FROM V$SYSSTAT WHERE NAME = 'physical reads'"));
3257 pDb->GetNext();
3258 if (pDb->GetData(1, SQL_C_ULONG, &physReads, 0, &cb))
3259 {
3260 t.sprintf(wxT("%s: %lu\n"), langDBINF_PHYSICAL_READS, physReads);
3261 s += t;
3262 }
3263
3264 ULONG hitRatio = (ULONG)((1.00 - ((float)physReads / (float)(dbBlockGets + consistentGets))) * 100.00);
3265 t.sprintf(wxT("*** %s: %lu%%\n"), langDBINF_CACHE_HIT_RATIO, hitRatio);
3266 s += t;
3267
3268 // Tablespace information
3269 s += wxT("\n");
3270 s += langDBINF_TABLESPACE_IO;
3271 s += wxT("\n");
3272 ULONG physWrites;
3273 char tablespaceName[256+1];
3274 pDb->ExecSql(wxT("SELECT NAME,PHYRDS,PHYWRTS FROM V$DATAFILE, V$FILESTAT WHERE V$DATAFILE.FILE# = V$FILESTAT.FILE#"));
3275 while (pDb->GetNext())
3276 {
3277 pDb->GetData(1, SQL_C_WXCHAR, tablespaceName, 256, &cb);
3278 pDb->GetData(2, SQL_C_ULONG, &physReads, 0, &cb);
3279 pDb->GetData(3, SQL_C_ULONG, &physWrites, 0, &cb);
3280 t.sprintf(wxT("%s\n\t%s: %lu\t%s: %lu\n"), tablespaceName,
3281 langDBINF_PHYSICAL_READS, physReads, langDBINF_PHYSICAL_WRITES, physWrites);
3282 s += t;
3283 }
3284
3285 s += wxT("\n");
3286 }
3287
3288 s += wxT("End of Diagnostics\n");
3289 wxLogMessage(s);
3290
3291 } // DisplayDbDiagnostics()
3292
3293 #if wxUSE_GRID
3294
3295 BEGIN_EVENT_TABLE(DbGridFrame, wxFrame)
3296 // EVT_CLOSE(DbGridFrame::OnCloseWindow)
3297 END_EVENT_TABLE()
3298
3299
3300 DbGridFrame::DbGridFrame(wxWindow *parent)
3301 : wxFrame (parent, wxID_ANY, wxT("Database Table"),
3302 wxDefaultPosition, wxSize(400, 325))
3303 {
3304 initialized = false;
3305 }
3306
3307
3308 void DbGridFrame::OnCloseWindow(wxCloseEvent& WXUNUSED(event))
3309 {
3310 this->Destroy();
3311 }
3312
3313
3314 bool DbGridFrame::Initialize()
3315 {
3316 wxGrid *grid = new wxGrid(this, wxID_ANY, wxDefaultPosition);
3317
3318 grid->RegisterDataType(wxGRID_VALUE_DATETIME,
3319 new wxGridCellDateTimeRenderer(wxT("%d %b %Y")),
3320 new wxGridCellTextEditor);
3321 #ifdef CHOICEINT
3322 grid->RegisterDataType(wxGRID_VALUE_CHOICEINT,
3323 new wxGridCellEnumRenderer,
3324 new wxGridCellEnumEditor);
3325
3326 wxString NativeLangChoice( wxString::Format(wxT("%s:%s,%s,%s,%s,%s"),wxGRID_VALUE_CHOICEINT,
3327 wxT("English"),
3328 wxT("French"),
3329 wxT("German"),
3330 wxT("Spanish"),
3331 wxT("Other") ));
3332 #endif
3333
3334 // Columns must match the sequence specified in SetColDef() calls
3335 wxDbGridColInfo* cols =
3336 new wxDbGridColInfo( 0,wxGRID_VALUE_STRING,wxT("Name"),
3337 new wxDbGridColInfo( 1,wxGRID_VALUE_STRING,wxT("Address 1"),
3338 new wxDbGridColInfo( 2,wxGRID_VALUE_STRING,wxT("Address 2"),
3339 new wxDbGridColInfo( 3,wxGRID_VALUE_STRING,wxT("City"),
3340 new wxDbGridColInfo( 4,wxGRID_VALUE_STRING,wxT("State"),
3341 new wxDbGridColInfo( 5,wxGRID_VALUE_STRING,wxT("PostCode"),
3342 new wxDbGridColInfo( 6,wxGRID_VALUE_STRING,wxT("Country"),
3343 new wxDbGridColInfo( 7,wxGRID_VALUE_DBAUTO,wxT("Join Date"),
3344 new wxDbGridColInfo( 8,wxGRID_VALUE_BOOL, wxT("Developer"),
3345 new wxDbGridColInfo( 9,wxGRID_VALUE_NUMBER,wxT("Contributions"),
3346 new wxDbGridColInfo(10,wxGRID_VALUE_NUMBER,wxT("Lines Of Code"),
3347 #ifdef CHOICEINT
3348 new wxDbGridColInfo(11,NativeLangChoice, wxT("Native Language"),NULL))))))))))));
3349 #else
3350 new wxDbGridColInfo(11,wxGRID_VALUE_NUMBER,wxT("Native Language"),NULL))))))))))));
3351 #endif
3352
3353 Ccontact *Contact = new Ccontact();
3354 //wxGetApp().Contact
3355
3356 if (!Contact)
3357 {
3358 wxMessageBox(wxT("Unable to instantiate an instance of Ccontact"), wxT("Error..."), wxOK | wxICON_EXCLAMATION);
3359 return false;
3360 }
3361
3362 if (!Contact->Open())
3363 {
3364 if (Contact->GetDb()->TableExists(CONTACT_TABLE_NAME, Contact->GetDb()->GetUsername(),
3365 wxGetApp().DbConnectInf->GetDefaultDir()))
3366 {
3367 wxString tStr;
3368 tStr.Printf(wxT("Unable to open the table '%s'.\n\n"),CONTACT_TABLE_NAME.c_str());
3369 wxMessageBox(wxDbLogExtendedErrorMsg(tStr.c_str(),wxGetApp().Contact->GetDb(),__TFILE__,__LINE__),
3370 wxT("ODBC Error..."),wxOK | wxICON_EXCLAMATION);
3371 }
3372
3373 return false;
3374 }
3375
3376 // Execute the following query using the cursor designated
3377 // for full table query
3378 Contact->SetRowMode(wxDbTable::WX_ROW_MODE_QUERY);
3379
3380 if (!Contact->Query())
3381 {
3382 wxString tStr;
3383 tStr = wxT("ODBC error during Query()\n\n");
3384 wxMessageBox(wxDbLogExtendedErrorMsg(tStr.c_str(),wxGetApp().Contact->GetDb(),__TFILE__,__LINE__),
3385 wxT("ODBC Error..."),wxOK | wxICON_EXCLAMATION);
3386 return false;
3387 }
3388
3389 // No data has been read in from the database yet, so
3390 // we need to initialize the data members to valid values
3391 // so Fit() can correctly size the grid
3392 Contact->Initialize();
3393
3394 wxDbGridTableBase* db = new wxDbGridTableBase(Contact, cols, wxUSE_QUERY, true);
3395
3396 delete cols;
3397
3398 grid->SetTable(db,true);
3399 grid->SetMargins(0, 0);
3400
3401 grid->Fit();
3402 wxSize size = grid->GetSize();
3403 size.x += 10;
3404 size.y += 10;
3405 SetClientSize(size);
3406 initialized = true;
3407 return true;
3408 } // DbGridFrame::Initialize()
3409
3410 #endif // #if wxUSE_GRID
3411
3412 /*
3413 TEST CODE FOR TESTING THE wxDbCreateDataSource() FUNCTION
3414
3415 int result = 0;
3416 result = wxDbCreateDataSource(wxT("Microsoft Access Driver (*.mdb)"), wxT("GLT-TEST2"), wxT("GLT-Descrip"), false, wxEmptyString, this);
3417 if (!result)
3418 {
3419 // check for errors caused by ConfigDSN based functions
3420 DWORD retcode = 0;
3421 WORD cb;
3422 wxChar errMsg[500+1];
3423 errMsg[0] = wxT('\0');
3424
3425 SQLInstallerError(1, &retcode, errMsg, 500, &cb);
3426
3427 wxMessageBox(wxT("FAILED creating data source"), wxT("FAILED"));
3428 }
3429 else
3430 wxMessageBox(wxT("SUCCEEDED creating data source"), wxT("SUCCESS"));
3431 */
3432
3433