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