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