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