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