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