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