1 ///////////////////////////////////////////////////////////////////////////////
3 // Purpose: wxWindows database demo app
4 // Author: George Tasker
8 // Copyright: (c) 1998 Remstar International, Inc.
9 // Licence: wxWindows licence
10 ///////////////////////////////////////////////////////////////////////////////
15 This sample program demonstrates the cross-platform ODBC database classes
16 donated by the development team at Remstar International.
18 The table this sample is based on is developer contact table, and shows
19 some of the simple uses of the database classes wxDb and wxDbTable.
25 #pragma implementation "dbtest.h"
28 #include "wx/wxprec.h"
42 #include <stdio.h> /* Included strictly for reading the text file with the database parameters */
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 */
47 //extern wxDbList WXDLLEXPORT *PtrBegDbList; /* from db.cpp, used in getting back error results from db connections */
49 #include "dbtest.h" /* Header file for this demonstration program */
50 #include "listdb.h" /* Code to support the "Lookup" button on the editor dialog */
52 IMPLEMENT_APP(DatabaseDemoApp
)
54 extern wxChar ListDB_Selection
[]; /* Used to return the first column value for the selected line from the listDB routines */
55 extern wxChar ListDB_Selection2
[]; /* Used to return the second column value for the selected line from the listDB routines */
57 const char *GetExtendedDBErrorMsg(wxDb
*pDb
, char *ErrFile
, int ErrLine
)
64 if (ErrFile
|| ErrLine
)
68 msg
+= wxT(" Line: ");
69 tStr
.Printf(wxT("%d"),ErrLine
);
74 msg
.Append (wxT("\nODBC errors:\n"));
77 // Display errors for this connection
79 for (i
= 0; i
< DB_MAX_ERROR_HISTORY
; i
++)
81 if (pDb
->errorList
[i
])
83 msg
.Append(pDb
->errorList
[i
]);
84 if (wxStrcmp(pDb
->errorList
[i
],wxT("")) != 0)
85 msg
.Append(wxT("\n"));
86 // Clear the errmsg buffer so the next error will not
87 // end up showing the previous error that have occurred
88 wxStrcpy(pDb
->errorList
[i
],wxT(""));
94 } // GetExtendedDBErrorMsg
97 bool DataTypeSupported(wxDb
*pDb
, SWORD datatype
)
99 wxDbSqlTypeInfo sqlTypeInfo
;
101 bool breakpoint
= FALSE
;
103 if (pDb
->GetDataTypeInfo(datatype
, sqlTypeInfo
))
108 } // GetDataTypesSupported();
112 void CheckSupportForAllDataTypes(wxDb
*pDb
)
114 wxLogMessage("\nThe following datatypes are supported by the\ndatabase you are currently connected to:");
116 if (DataTypeSupported(pDb
,SQL_C_BINARY
))
117 wxLogMessage("SQL_C_BINARY");
120 if (DataTypeSupported(pDb
,SQL_C_BIT
))
121 wxLogMessage("SQL_C_BIT");
123 #ifdef SQL_C_BOOKMARK
124 if (DataTypeSupported(pDb
,SQL_C_BOOKMARK
))
125 wxLogMessage("SQL_C_BOOKMARK");
128 if (DataTypeSupported(pDb
,SQL_C_CHAR
))
129 wxLogMessage("SQL_C_CHAR");
132 if (DataTypeSupported(pDb
,SQL_C_DATE
))
133 wxLogMessage("SQL_C_DATE");
136 if (DataTypeSupported(pDb
,SQL_C_DEFAULT
))
137 wxLogMessage("SQL_C_DEFAULT");
140 if (DataTypeSupported(pDb
,SQL_C_DOUBLE
))
141 wxLogMessage("SQL_C_DOUBLE");
144 if (DataTypeSupported(pDb
,SQL_C_FLOAT
))
145 wxLogMessage("SQL_C_FLOAT");
148 if (DataTypeSupported(pDb
,SQL_C_GUID
))
149 wxLogMessage("SQL_C_GUID");
151 #ifdef SQL_C_INTERVAL_DAY
152 if (DataTypeSupported(pDb
,SQL_C_INTERVAL_DAY
))
153 wxLogMessage("SQL_C_INTERVAL_DAY");
155 #ifdef SQL_C_INTERVAL_DAY_TO_HOUR
156 if (DataTypeSupported(pDb
,SQL_C_INTERVAL_DAY_TO_HOUR
))
157 wxLogMessage("SQL_C_INTERVAL_DAY_TO_HOUR");
159 #ifdef SQL_C_INTERVAL_DAY_TO_MINUTE
160 if (DataTypeSupported(pDb
,SQL_C_INTERVAL_DAY_TO_MINUTE
))
161 wxLogMessage("SQL_C_INTERVAL_DAY_TO_MINUTE");
163 #ifdef SQL_C_INTERVAL_DAY_TO_SECOND
164 if (DataTypeSupported(pDb
,SQL_C_INTERVAL_DAY_TO_SECOND
))
165 wxLogMessage("SQL_C_INTERVAL_DAY_TO_SECOND");
167 #ifdef SQL_C_INTERVAL_HOUR
168 if (DataTypeSupported(pDb
,SQL_C_INTERVAL_HOUR
))
169 wxLogMessage("SQL_C_INTERVAL_HOUR");
171 #ifdef SQL_C_INTERVAL_HOUR_TO_MINUTE
172 if (DataTypeSupported(pDb
,SQL_C_INTERVAL_HOUR_TO_MINUTE
))
173 wxLogMessage("SQL_C_INTERVAL_HOUR_TO_MINUTE");
175 #ifdef SQL_C_INTERVAL_HOUR_TO_SECOND
176 if (DataTypeSupported(pDb
,SQL_C_INTERVAL_HOUR_TO_SECOND
))
177 wxLogMessage("SQL_C_INTERVAL_HOUR_TO_SECOND");
179 #ifdef SQL_C_INTERVAL_MINUTE
180 if (DataTypeSupported(pDb
,SQL_C_INTERVAL_MINUTE
))
181 wxLogMessage("SQL_C_INTERVAL_MINUTE");
183 #ifdef SQL_C_INTERVAL_MINUTE_TO_SECOND
184 if (DataTypeSupported(pDb
,SQL_C_INTERVAL_MINUTE_TO_SECOND
))
185 wxLogMessage("SQL_C_INTERVAL_MINUTE_TO_SECOND");
187 #ifdef SQL_C_INTERVAL_MONTH
188 if (DataTypeSupported(pDb
,SQL_C_INTERVAL_MONTH
))
189 wxLogMessage("SQL_C_INTERVAL_MONTH");
191 #ifdef SQL_C_INTERVAL_SECOND
192 if (DataTypeSupported(pDb
,SQL_C_INTERVAL_SECOND
))
193 wxLogMessage("SQL_C_INTERVAL_SECOND");
195 #ifdef SQL_C_INTERVAL_YEAR
196 if (DataTypeSupported(pDb
,SQL_C_INTERVAL_YEAR
))
197 wxLogMessage("SQL_C_INTERVAL_YEAR");
199 #ifdef SQL_C_INTERVAL_YEAR_TO_MONTH
200 if (DataTypeSupported(pDb
,SQL_C_INTERVAL_YEAR_TO_MONTH
))
201 wxLogMessage("SQL_C_INTERVAL_YEAR_TO_MONTH");
204 if (DataTypeSupported(pDb
,SQL_C_LONG
))
205 wxLogMessage("SQL_C_LONG");
208 if (DataTypeSupported(pDb
,SQL_C_NUMERIC
))
209 wxLogMessage("SQL_C_NUMERIC");
212 if (DataTypeSupported(pDb
,SQL_C_SBIGINT
))
213 wxLogMessage("SQL_C_SBIGINT");
216 if (DataTypeSupported(pDb
,SQL_C_SHORT
))
217 wxLogMessage("SQL_C_SHORT");
220 if (DataTypeSupported(pDb
,SQL_C_SLONG
))
221 wxLogMessage("SQL_C_SLONG");
224 if (DataTypeSupported(pDb
,SQL_C_SSHORT
))
225 wxLogMessage("SQL_C_SSHORT");
227 #ifdef SQL_C_STINYINT
228 if (DataTypeSupported(pDb
,SQL_C_STINYINT
))
229 wxLogMessage("SQL_C_STINYINT");
232 if (DataTypeSupported(pDb
,SQL_C_TIME
))
233 wxLogMessage("SQL_C_TIME");
235 #ifdef SQL_C_TIMESTAMP
236 if (DataTypeSupported(pDb
,SQL_C_TIMESTAMP
))
237 wxLogMessage("SQL_C_TIMESTAMP");
240 if (DataTypeSupported(pDb
,SQL_C_TINYINT
))
241 wxLogMessage("SQL_C_TINYINT");
243 #ifdef SQL_C_TYPE_DATE
244 if (DataTypeSupported(pDb
,SQL_C_TYPE_DATE
))
245 wxLogMessage("SQL_C_TYPE_DATE");
247 #ifdef SQL_C_TYPE_TIME
248 if (DataTypeSupported(pDb
,SQL_C_TYPE_TIME
))
249 wxLogMessage("SQL_C_TYPE_TIME");
251 #ifdef SQL_C_TYPE_TIMESTAMP
252 if (DataTypeSupported(pDb
,SQL_C_TYPE_TIMESTAMP
))
253 wxLogMessage("SQL_C_TYPE_TIMESTAMP");
256 if (DataTypeSupported(pDb
,SQL_C_UBIGINT
))
257 wxLogMessage("SQL_C_UBIGINT");
260 if (DataTypeSupported(pDb
,SQL_C_ULONG
))
261 wxLogMessage("SQL_C_ULONG");
264 if (DataTypeSupported(pDb
,SQL_C_USHORT
))
265 wxLogMessage("SQL_C_USHORT");
267 #ifdef SQL_C_UTINYINT
268 if (DataTypeSupported(pDb
,SQL_C_UTINYINT
))
269 wxLogMessage("SQL_C_UTINYINT");
271 #ifdef SQL_C_VARBOOKMARK
272 if (DataTypeSupported(pDb
,SQL_C_VARBOOKMARK
))
273 wxLogMessage("SQL_C_VARBOOKMARK");
276 // Extended SQL types
278 if (DataTypeSupported(pDb
,SQL_DATE
))
279 wxLogMessage("SQL_DATE");
282 if (DataTypeSupported(pDb
,SQL_INTERVAL
))
283 wxLogMessage("SQL_INTERVAL");
286 if (DataTypeSupported(pDb
,SQL_TIME
))
287 wxLogMessage("SQL_TIME");
290 if (DataTypeSupported(pDb
,SQL_TIMESTAMP
))
291 wxLogMessage("SQL_TIMESTAMP");
293 #ifdef SQL_LONGVARCHAR
294 if (DataTypeSupported(pDb
,SQL_LONGVARCHAR
))
295 wxLogMessage("SQL_LONGVARCHAR");
298 if (DataTypeSupported(pDb
,SQL_BINARY
))
299 wxLogMessage("SQL_BINARY");
302 if (DataTypeSupported(pDb
,SQL_VARBINARY
))
303 wxLogMessage("SQL_VARBINARY");
305 #ifdef SQL_LONGVARBINARY
306 if (DataTypeSupported(pDb
,SQL_LONGVARBINARY
))
307 wxLogMessage("SQL_LONGVARBINARY");
310 if (DataTypeSupported(pDb
,SQL_BIGINT
))
311 wxLogMessage("SQL_BIGINT");
314 if (DataTypeSupported(pDb
,SQL_TINYINT
))
315 wxLogMessage("SQL_TINYINT");
318 if (DataTypeSupported(pDb
,SQL_BIT
))
319 wxLogMessage("SQL_BIT");
322 if (DataTypeSupported(pDb
,SQL_GUID
))
323 wxLogMessage("SQL_GUID");
327 if (DataTypeSupported(pDb
,SQL_CHAR
))
328 wxLogMessage("SQL_CHAR");
331 if (DataTypeSupported(pDb
,SQL_INTEGER
))
332 wxLogMessage("SQL_INTEGER");
335 if (DataTypeSupported(pDb
,SQL_SMALLINT
))
336 wxLogMessage("SQL_SMALLINT");
339 if (DataTypeSupported(pDb
,SQL_REAL
))
340 wxLogMessage("SQL_REAL");
343 if (DataTypeSupported(pDb
,SQL_DOUBLE
))
344 wxLogMessage("SQL_DOUBLE");
347 if (DataTypeSupported(pDb
,SQL_NUMERIC
))
348 wxLogMessage("SQL_NUMERIC");
351 if (DataTypeSupported(pDb
,SQL_DATE
))
352 wxLogMessage("SQL_DATE");
355 if (DataTypeSupported(pDb
,SQL_TIME
))
356 wxLogMessage("SQL_TIME");
359 if (DataTypeSupported(pDb
,SQL_TIMESTAMP
))
360 wxLogMessage("SQL_TIMESTAMP");
363 if (DataTypeSupported(pDb
,SQL_VARCHAR
))
364 wxLogMessage("SQL_VARCHAR");
369 if (DataTypeSupported(pDb
,SQL_C_TCHAR
))
370 wxLogMessage("SQL_C_TCHAR (Unicode support is possible)");
374 } // CheckSupportForAllDataTypes()
377 bool DatabaseDemoApp::OnInit()
382 // Create the main frame window
383 DemoFrame
= new DatabaseDemoFrame(NULL
, wxT("wxWindows Database Demo"), wxPoint(50, 50), wxSize(537, 480));
386 DemoFrame
->SetIcon(wxICON(db
));
389 wxMenu
*file_menu
= new wxMenu
;
390 file_menu
->Append(FILE_CREATE
, wxT("&Create CONTACT table"));
391 file_menu
->Append(FILE_RECREATE_TABLE
, wxT("&Recreate CONTACT table"));
392 file_menu
->Append(FILE_RECREATE_INDEXES
, wxT("&Recreate CONTACT indexes"));
393 file_menu
->Append(FILE_EXIT
, wxT("E&xit"));
395 wxMenu
*edit_menu
= new wxMenu
;
396 edit_menu
->Append(EDIT_PARAMETERS
, wxT("&Parameters..."));
398 wxMenu
*help_menu
= new wxMenu
;
399 help_menu
->Append(HELP_ABOUT
, wxT("&About"));
401 wxMenuBar
*menu_bar
= new wxMenuBar
;
402 menu_bar
->Append(file_menu
, wxT("&File"));
403 menu_bar
->Append(edit_menu
, wxT("&Edit"));
404 menu_bar
->Append(help_menu
, wxT("&Help"));
405 DemoFrame
->SetMenuBar(menu_bar
);
407 params
.ODBCSource
[0] = 0;
408 params
.UserName
[0] = 0;
409 params
.Password
[0] = 0;
410 params
.DirPath
[0] = 0;
413 DemoFrame
->Show(TRUE
);
415 // Passing NULL for the SQL environment handle causes
416 // the wxDbConnectInf constructor to obtain a handle
419 // WARNING: Be certain that you do not free this handle
420 // directly with SQLFreeEnv(). Use either the
421 // method ::FreeHenv() or delete the DbConnectInf.
422 DbConnectInf
= new wxDbConnectInf(NULL
, params
.ODBCSource
, params
.UserName
,
423 params
.Password
, params
.DirPath
);
425 if (!DbConnectInf
|| !DbConnectInf
->GetHenv())
427 wxMessageBox(wxT("Unable to define data source connection info."), wxT("DB CONNECTION ERROR..."),wxOK
| wxICON_EXCLAMATION
);
428 wxDELETE(DbConnectInf
);
431 if (!ReadParamFile(params
))
432 DemoFrame
->BuildParameterDialog(NULL
);
434 if (!wxStrlen(params
.ODBCSource
))
436 wxDELETE(DbConnectInf
);
440 DbConnectInf
->SetDsn(params
.ODBCSource
);
441 DbConnectInf
->SetUserID(params
.UserName
);
442 DbConnectInf
->SetPassword(params
.Password
);
443 DbConnectInf
->SetDefaultDir(params
.DirPath
);
445 READONLY_DB
= wxDbGetConnection(DbConnectInf
);
446 if (READONLY_DB
== 0)
448 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
);
449 DemoFrame
->BuildParameterDialog(NULL
);
450 wxDELETE(DbConnectInf
);
451 wxMessageBox(wxT("Now exiting program.\n\nRestart program to try any new settings."),wxT("Notice..."),wxOK
| wxICON_INFORMATION
);
455 DemoFrame
->BuildEditorDialog();
458 DemoFrame
->Refresh();
461 } // DatabaseDemoApp::OnInit()
464 bool DatabaseDemoApp::ReadParamFile(Cparameters
¶ms
)
467 if ((paramFile
= fopen(PARAM_FILENAME
, wxT("r"))) == NULL
)
470 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
);
471 wxMessageBox(tStr
,wxT("File I/O Error..."),wxOK
| wxICON_EXCLAMATION
);
476 wxChar buffer
[1000+1];
477 fgets(buffer
, sizeof(params
.ODBCSource
), paramFile
);
478 buffer
[wxStrlen(buffer
)-1] = wxT('\0');
479 wxStrcpy(params
.ODBCSource
,buffer
);
481 fgets(buffer
, sizeof(params
.UserName
), paramFile
);
482 buffer
[wxStrlen(buffer
)-1] = wxT('\0');
483 wxStrcpy(params
.UserName
,buffer
);
485 fgets(buffer
, sizeof(params
.Password
), paramFile
);
486 buffer
[wxStrlen(buffer
)-1] = wxT('\0');
487 wxStrcpy(params
.Password
,buffer
);
489 fgets(buffer
, sizeof(params
.DirPath
), paramFile
);
490 buffer
[wxStrlen(buffer
)-1] = wxT('\0');
491 wxStrcpy(params
.DirPath
,buffer
);
496 } // DatabaseDemoApp::ReadParamFile()
499 bool DatabaseDemoApp::WriteParamFile(Cparameters
¶ms
)
502 if ((paramFile
= fopen(PARAM_FILENAME
, wxT("wt"))) == NULL
)
505 tStr
.Printf(wxT("Unable to write/overwrite '%s'."),PARAM_FILENAME
);
506 wxMessageBox(tStr
,wxT("File I/O Error..."),wxOK
| wxICON_EXCLAMATION
);
510 fputs(wxGetApp().params
.ODBCSource
, paramFile
);
511 fputc(wxT('\n'), paramFile
);
512 fputs(wxGetApp().params
.UserName
, paramFile
);
513 fputc(wxT('\n'), paramFile
);
514 fputs(wxGetApp().params
.Password
, paramFile
);
515 fputc(wxT('\n'), paramFile
);
516 fputs(wxGetApp().params
.DirPath
, paramFile
);
517 fputc(wxT('\n'), paramFile
);
521 } // DatabaseDemoApp::WriteParamFile()
524 void DatabaseDemoApp::CreateDataTable(bool recreate
)
528 Ok
= (wxMessageBox(wxT("Any data currently residing in the table will be erased.\n\nAre you sure?"),wxT("Confirm"),wxYES_NO
|wxICON_QUESTION
) == wxYES
);
537 Contact
->GetDb()->RollbackTrans(); // Make sure the current cursor is in a known/stable state
539 if (!Contact
->CreateTable(recreate
))
543 tStr
= wxT("Error creating CONTACTS table.\nTable was not created.\n\n");
544 tStr
+= GetExtendedDBErrorMsg(Contact
->GetDb(),__FILE__
,__LINE__
);
545 wxMessageBox(tStr
,wxT("ODBC Error..."),wxOK
| wxICON_EXCLAMATION
);
550 if (!Contact
->CreateIndexes())
554 tStr
= wxT("Error creating CONTACTS indexes.\nIndexes will be unavailable.\n\n");
555 tStr
+= GetExtendedDBErrorMsg(Contact
->GetDb(),__FILE__
,__LINE__
);
556 wxMessageBox(tStr
,wxT("ODBC Error..."),wxOK
| wxICON_EXCLAMATION
);
564 wxMessageBox(wxT("Table and index(es) were successfully created."),wxT("Notice..."),wxOK
| wxICON_INFORMATION
);
565 } // DatabaseDemoApp::CreateDataTable()
568 BEGIN_EVENT_TABLE(DatabaseDemoFrame
, wxFrame
)
569 EVT_MENU(FILE_CREATE
, DatabaseDemoFrame::OnCreate
)
570 EVT_MENU(FILE_RECREATE_TABLE
, DatabaseDemoFrame::OnRecreateTable
)
571 EVT_MENU(FILE_RECREATE_INDEXES
, DatabaseDemoFrame::OnRecreateIndexes
)
572 EVT_MENU(FILE_EXIT
, DatabaseDemoFrame::OnExit
)
573 EVT_MENU(EDIT_PARAMETERS
, DatabaseDemoFrame::OnEditParameters
)
574 EVT_MENU(HELP_ABOUT
, DatabaseDemoFrame::OnAbout
)
575 EVT_CLOSE(DatabaseDemoFrame::OnCloseWindow
)
579 // DatabaseDemoFrame constructor
580 DatabaseDemoFrame::DatabaseDemoFrame(wxFrame
*frame
, const wxString
& title
,
581 const wxPoint
& pos
, const wxSize
& size
):
582 wxFrame(frame
, -1, title
, pos
, size
)
584 // Put any code in necessary for initializing the main frame here
588 delete wxLog::SetActiveTarget(new wxLogStderr
);
590 } // DatabaseDemoFrame constructor
592 DatabaseDemoFrame::~DatabaseDemoFrame()
594 delete wxLog::SetActiveTarget(NULL
);
595 } // DatabaseDemoFrame destructor
598 void DatabaseDemoFrame::OnCreate(wxCommandEvent
& event
)
600 wxGetApp().CreateDataTable(FALSE
);
601 } // DatabaseDemoFrame::OnCreate()
604 void DatabaseDemoFrame::OnRecreateTable(wxCommandEvent
& event
)
606 wxGetApp().CreateDataTable(TRUE
);
607 } // DatabaseDemoFrame::OnRecreate()
610 void DatabaseDemoFrame::OnRecreateIndexes(wxCommandEvent
& event
)
612 if (!wxGetApp().Contact
->CreateIndexes())
617 tStr
= wxT("Error creating CONTACTS indexes.\nNew indexes will be unavailable.\n\n");
618 tStr
+= GetExtendedDBErrorMsg(wxGetApp().Contact
->GetDb(),__FILE__
,__LINE__
);
619 wxMessageBox(tStr
,wxT("ODBC Error..."),wxOK
| wxICON_EXCLAMATION
);
622 wxMessageBox(wxT("Index(es) were successfully recreated."),wxT("Notice..."),wxOK
| wxICON_INFORMATION
);
624 } // DatabaseDemoFrame::OnRecreateIndexes()
627 void DatabaseDemoFrame::OnExit(wxCommandEvent
& event
)
630 } // DatabaseDemoFrame::OnExit()
633 void DatabaseDemoFrame::OnEditParameters(wxCommandEvent
& event
)
635 if ((pEditorDlg
->mode
!= mCreate
) && (pEditorDlg
->mode
!= mEdit
))
636 BuildParameterDialog(this);
638 wxMessageBox(wxT("Cannot change database parameters while creating or editing a record"),wxT("Notice..."),wxOK
| wxICON_INFORMATION
);
639 } // DatabaseDemoFrame::OnEditParameters()
642 void DatabaseDemoFrame::OnAbout(wxCommandEvent
& event
)
644 wxMessageBox(wxT("wxWindows sample program for database classes\n\nContributed on 27 July 1998"),wxT("About..."),wxOK
| wxICON_INFORMATION
);
645 } // DatabaseDemoFrame::OnAbout()
648 // Put any additional checking necessary to make certain it is alright
649 // to close the program here that is not done elsewhere
650 void DatabaseDemoFrame::OnCloseWindow(wxCloseEvent
& event
)
653 if (pEditorDlg
&& pEditorDlg
->Close())
664 wxDELETE(wxGetApp().Contact
);
666 // This function will close all the connections to the database that have been
667 // previously cached.
668 wxDbCloseConnections();
670 // Deletion of the wxDbConnectInf instance must be the LAST thing done that
671 // has anything to do with the database. Deleting this before disconnecting,
672 // freeing/closing connections, etc will result in a crash!
673 wxDELETE(wxGetApp().DbConnectInf
);
677 } // DatabaseDemoFrame::OnCloseWindow()
680 void DatabaseDemoFrame::BuildEditorDialog()
683 pEditorDlg
= new CeditorDlg(this);
686 pEditorDlg
->Initialize();
687 if (!pEditorDlg
->initialized
)
691 wxMessageBox(wxT("Unable to initialize the editor dialog for some reason"),wxT("Error..."),wxOK
| wxICON_EXCLAMATION
);
697 wxMessageBox(wxT("Unable to create the editor dialog for some reason"),wxT("Error..."),wxOK
| wxICON_EXCLAMATION
);
700 } // DatabaseDemoFrame::BuildEditorDialog()
703 void DatabaseDemoFrame::BuildParameterDialog(wxWindow
*parent
)
705 pParamDlg
= new CparameterDlg(parent
);
708 wxMessageBox(wxT("Unable to create the parameter dialog for some reason"),wxT("Error..."),wxOK
| wxICON_EXCLAMATION
);
709 } // DatabaseDemoFrame::BuildParameterDialog()
713 * Constructor note: If no wxDb object is passed in, a new connection to the database
714 * is created for this instance of Ccontact. This can be a slow process depending
715 * on the database engine being used, and some database engines have a limit on the
716 * number of connections (either hard limits, or license restricted) so care should
717 * be used to use as few connections as is necessary.
719 * IMPORTANT: Objects which share a wxDb pointer are ALL acted upon whenever a member
720 * function of pDb is called (i.e. CommitTrans() or RollbackTrans(), so if modifying
721 * or creating a table objects which use the same pDb, know that all the objects
722 * will be committed or rolled back when any of the objects has this function call made.
724 Ccontact::Ccontact (wxDb
*pwxDb
) : wxDbTable(pwxDb
? pwxDb
: wxDbGetConnection(wxGetApp().DbConnectInf
),
725 CONTACT_TABLE_NAME
, CONTACT_NO_COLS
, wxT(""),
726 !wxDB_QUERY_ONLY
, wxGetApp().DbConnectInf
->GetDefaultDir())
728 // This is used to represent whether the database connection should be released
729 // when this instance of the object is deleted. If using the same connection
730 // for multiple instance of database objects, then the connection should only be
731 // released when the last database instance using the connection is deleted
735 GetDb()->SetSqlLogging(sqlLogON
);
739 } // Ccontact Constructor
742 void Ccontact::Initialize()
751 JoinDate
.year
= 1980;
757 JoinDate
.fraction
= 0;
758 NativeLanguage
= langENGLISH
;
762 } // Ccontact::Initialize
765 Ccontact::~Ccontact()
769 if (!wxDbFreeConnection(GetDb()))
772 tStr
= wxT("Unable to Free the Ccontact data table handle\n\n");
773 tStr
+= GetExtendedDBErrorMsg(GetDb(),__FILE__
,__LINE__
);
774 wxMessageBox(tStr
,wxT("ODBC Error..."),wxOK
| wxICON_EXCLAMATION
);
777 } // Ccontract destructor
781 * Handles setting up all the connections for the interface from the wxDbTable
782 * functions to interface to the data structure used to store records in
783 * memory, and for all the column definitions that define the table structure
785 void Ccontact::SetupColumns()
787 // NOTE: Columns now are 8 character names, as that is all dBase can support. Longer
788 // names can be used for other database engines
789 SetColDefs ( 0,wxT("NAME"), DB_DATA_TYPE_VARCHAR
, Name
, SQL_C_CHAR
, sizeof(Name
), TRUE
, TRUE
); // Primary index
790 SetColDefs ( 1,wxT("ADDRESS1"), DB_DATA_TYPE_VARCHAR
, Addr1
, SQL_C_CHAR
, sizeof(Addr1
), FALSE
,TRUE
);
791 SetColDefs ( 2,wxT("ADDRESS2"), DB_DATA_TYPE_VARCHAR
, Addr2
, SQL_C_CHAR
, sizeof(Addr2
), FALSE
,TRUE
);
792 SetColDefs ( 3,wxT("CITY"), DB_DATA_TYPE_VARCHAR
, City
, SQL_C_CHAR
, sizeof(City
), FALSE
,TRUE
);
793 SetColDefs ( 4,wxT("STATE"), DB_DATA_TYPE_VARCHAR
, State
, SQL_C_CHAR
, sizeof(State
), FALSE
,TRUE
);
794 SetColDefs ( 5,wxT("POSTCODE"), DB_DATA_TYPE_VARCHAR
, PostalCode
, SQL_C_CHAR
, sizeof(PostalCode
), FALSE
,TRUE
);
795 SetColDefs ( 6,wxT("COUNTRY"), DB_DATA_TYPE_VARCHAR
, Country
, SQL_C_CHAR
, sizeof(Country
), FALSE
,TRUE
);
796 SetColDefs ( 7,wxT("JOINDATE"), DB_DATA_TYPE_DATE
, &JoinDate
, SQL_C_TIMESTAMP
, sizeof(JoinDate
), FALSE
,TRUE
);
797 SetColDefs ( 8,wxT("IS_DEV"), DB_DATA_TYPE_INTEGER
, &IsDeveloper
, SQL_C_BOOLEAN(IsDeveloper
), sizeof(IsDeveloper
), FALSE
,TRUE
);
798 SetColDefs ( 9,wxT("CONTRIBS"), DB_DATA_TYPE_INTEGER
, &Contributions
, SQL_C_USHORT
, sizeof(Contributions
), FALSE
,TRUE
);
799 SetColDefs (10,wxT("LINE_CNT"), DB_DATA_TYPE_INTEGER
, &LinesOfCode
, SQL_C_ULONG
, sizeof(LinesOfCode
), FALSE
,TRUE
);
800 SetColDefs (11,wxT("LANGUAGE"), DB_DATA_TYPE_INTEGER
, &NativeLanguage
, SQL_C_ENUM
, sizeof(NativeLanguage
), FALSE
,TRUE
);
801 #if wxODBC_BLOB_EXPERIMENT > 0
802 SetColDefs (12,wxT("PICTURE"), DB_DATA_TYPE_BLOB
, Picture
, SQL_LONGVARBINARY
, sizeof(Picture
), FALSE
,TRUE
);
804 } // Ccontact::SetupColumns
807 bool Ccontact::CreateIndexes(void)
809 // This index could easily be accomplished with an "orderBy" clause,
810 // but is done to show how to construct a non-primary index.
812 wxDbIdxDef idxDef
[2];
816 wxStrcpy(idxDef
[0].ColName
, "IS_DEV");
817 idxDef
[0].Ascending
= TRUE
;
819 wxStrcpy(idxDef
[1].ColName
, "NAME");
820 idxDef
[1].Ascending
= TRUE
;
822 indexName
= GetTableName();
823 indexName
+= "_IDX1";
824 Ok
= CreateIndex(indexName
.c_str(), TRUE
, 2, idxDef
);
827 } // Ccontact::CreateIndexes()
831 * Having a function to do a query on the primary key (and possibly others) is
832 * very efficient and tighter coding so that it is available where ever the object
833 * is. Great for use with multiple tables when not using views or outer joins
835 bool Ccontact::FetchByName(const wxString
&name
)
837 whereStr
.Printf(wxT("NAME = '%s'"),name
.c_str());
838 SetWhereClause(whereStr
.c_str());
839 SetOrderByClause(wxT(""));
847 } // Ccontact::FetchByName()
852 * ************* DIALOGS ***************
857 /* CeditorDlg constructor
859 * Creates the dialog used for creating/editing/deleting/copying a Ccontact object.
860 * This dialog actually is drawn in the main frame of the program
862 * An instance of Ccontact is created - "Contact" - which is used to hold the Ccontact
863 * object that is currently being worked with.
866 BEGIN_EVENT_TABLE(CeditorDlg
, wxPanel
)
867 EVT_BUTTON(-1, CeditorDlg::OnButton
)
868 EVT_CLOSE(CeditorDlg::OnCloseWindow
)
871 CeditorDlg::CeditorDlg(wxWindow
*parent
) : wxPanel (parent
, 0, 0, 537, 480)
873 // Since the ::OnCommand() function is overridden, this prevents the widget
874 // detection in ::OnCommand() until all widgets have been initialized to prevent
875 // uninitialized pointers from crashing the program
876 widgetPtrsSet
= FALSE
;
883 } // CeditorDlg constructor
886 void CeditorDlg::OnCloseWindow(wxCloseEvent
& event
)
889 if ((mode
!= mCreate
) && (mode
!= mEdit
))
895 wxMessageBox(wxT("Must finish processing the current record being created/modified before exiting"),wxT("Notice..."),wxOK
| wxICON_INFORMATION
);
898 } // CeditorDlg::OnCloseWindow()
901 void CeditorDlg::OnButton(wxCommandEvent
&event
)
903 wxWindow
*win
= (wxWindow
*) event
.GetEventObject();
904 OnCommand( *win
, event
);
905 } // CeditorDlg::OnButton()
908 void CeditorDlg::OnCommand(wxWindow
& win
, wxCommandEvent
& event
)
912 widgetName
= win
.GetName();
917 if (widgetName
== pCreateBtn
->GetName())
919 wxGetApp().Contact
->Initialize();
922 pNameTxt
->SetValue(wxT(""));
923 pNameTxt
->SetFocus();
927 if (widgetName
== pEditBtn
->GetName())
929 saveName
= wxGetApp().Contact
->Name
;
931 pNameTxt
->SetFocus();
935 if (widgetName
== pCopyBtn
->GetName())
938 pNameTxt
->SetValue(wxT(""));
939 pNameTxt
->SetFocus();
943 if (widgetName
== pDeleteBtn
->GetName())
945 bool Ok
= (wxMessageBox(wxT("Are you sure?"),wxT("Confirm"),wxYES_NO
|wxICON_QUESTION
) == wxYES
);
950 if (Ok
&& wxGetApp().Contact
->Delete())
952 // NOTE: Deletions are not finalized until a CommitTrans() is performed.
953 // If the commit were not performed, the program will continue to
954 // show the table contents as if they were deleted until this instance
955 // of Ccontact is deleted. If the Commit wasn't performed, the
956 // database will automatically Rollback the changes when the database
957 // connection is terminated
958 wxGetApp().Contact
->GetDb()->CommitTrans();
960 // Try to get the row that followed the just deleted row in the orderBy sequence
963 // There was now row (in sequence) after the just deleted row, so get the
964 // row which preceded the just deleted row
967 // There are now no rows remaining, so clear the dialog widgets
968 wxGetApp().Contact
->Initialize();
972 SetMode(mode
); // force reset of button enable/disable
976 wxGetApp().Contact
->GetDb()->RollbackTrans();
982 if (widgetName
== pSaveBtn
->GetName())
988 if (widgetName
== pCancelBtn
->GetName())
990 bool Ok
= (wxMessageBox(wxT("Are you sure?"),wxT("Confirm"),wxYES_NO
|wxICON_QUESTION
) == wxYES
);
995 if (saveName
.IsEmpty())
997 wxGetApp().Contact
->Initialize();
1004 // Requery previous record
1005 if (wxGetApp().Contact
->FetchByName(saveName
))
1013 // Previous record not available, retrieve first record in table
1014 if (wxGetApp().Contact
->GetDb()->Dbms() != dbmsPOSTGRES
&&
1015 wxGetApp().Contact
->GetDb()->Dbms() != dbmsMY_SQL
)
1017 wxGetApp().Contact
->whereStr
= wxT("NAME = (SELECT MIN(NAME) FROM ");
1018 wxGetApp().Contact
->whereStr
+= wxGetApp().Contact
->GetTableName();
1019 wxGetApp().Contact
->whereStr
+= wxT(")");
1020 wxGetApp().Contact
->SetWhereClause(wxGetApp().Contact
->whereStr
.c_str());
1023 wxGetApp().Contact
->SetWhereClause(wxT(""));
1025 if (!wxGetApp().Contact
->Query())
1028 tStr
= wxT("ODBC error during Query()\n\n");
1029 tStr
+= GetExtendedDBErrorMsg(wxGetApp().Contact
->GetDb(),__FILE__
,__LINE__
);
1030 wxMessageBox(tStr
,wxT("ODBC Error..."),wxOK
| wxICON_EXCLAMATION
);
1034 if (wxGetApp().Contact
->GetNext()) // Successfully read first record
1040 // No contacts are available, clear dialog
1041 wxGetApp().Contact
->Initialize();
1047 if (widgetName
== pPrevBtn
->GetName())
1054 if (widgetName
== pNextBtn
->GetName())
1061 if (widgetName
== pQueryBtn
->GetName())
1063 // Display the query dialog box
1064 wxChar qryWhere
[DB_MAX_WHERE_CLAUSE_LEN
+1];
1065 wxStrcpy(qryWhere
, (const wxChar
*) wxGetApp().Contact
->qryWhereStr
);
1066 wxChar
*tblName
[] = {(wxChar
*)CONTACT_TABLE_NAME
, 0};
1067 new CqueryDlg(GetParent(), wxGetApp().Contact
->GetDb(), tblName
, qryWhere
);
1069 // Query the first record in the new record set and
1070 // display it, if the query string has changed.
1071 if (wxStrcmp(qryWhere
, (const wxChar
*) wxGetApp().Contact
->qryWhereStr
))
1073 wxGetApp().Contact
->whereStr
.Empty();
1074 wxGetApp().Contact
->SetOrderByClause("NAME");
1076 if (wxGetApp().Contact
->GetDb()->Dbms() != dbmsPOSTGRES
&&
1077 wxGetApp().Contact
->GetDb()->Dbms() != dbmsMY_SQL
)
1079 wxGetApp().Contact
->whereStr
= wxT("NAME = (SELECT MIN(NAME) FROM ");
1080 wxGetApp().Contact
->whereStr
+= CONTACT_TABLE_NAME
;
1083 // Append the query where string (if there is one)
1084 wxGetApp().Contact
->qryWhereStr
= qryWhere
;
1085 if (wxStrlen(qryWhere
))
1087 wxGetApp().Contact
->whereStr
+= wxT(" WHERE ");
1088 wxGetApp().Contact
->whereStr
+= wxGetApp().Contact
->qryWhereStr
;
1090 // Close the expression with a right paren
1091 wxGetApp().Contact
->whereStr
+= wxT(")");
1092 // Requery the table
1093 wxGetApp().Contact
->SetWhereClause(wxGetApp().Contact
->whereStr
.c_str());
1094 if (!wxGetApp().Contact
->Query())
1097 tStr
= wxT("ODBC error during Query()\n\n");
1098 tStr
+= GetExtendedDBErrorMsg(wxGetApp().Contact
->GetDb(),__FILE__
,__LINE__
);
1099 wxMessageBox(tStr
,wxT("ODBC Error..."),wxOK
| wxICON_EXCLAMATION
);
1102 // Display the first record from the query set
1103 if (!wxGetApp().Contact
->GetNext())
1104 wxGetApp().Contact
->Initialize();
1108 // Enable/Disable the reset button
1109 pResetBtn
->Enable(!wxGetApp().Contact
->qryWhereStr
.IsEmpty());
1115 if (widgetName
== pResetBtn
->GetName())
1117 // Clear the additional where criteria established by the query feature
1118 wxGetApp().Contact
->qryWhereStr
= wxT("");
1119 wxGetApp().Contact
->SetOrderByClause(wxT("NAME"));
1121 if (wxGetApp().Contact
->GetDb()->Dbms() != dbmsPOSTGRES
&&
1122 wxGetApp().Contact
->GetDb()->Dbms() != dbmsMY_SQL
)
1124 wxGetApp().Contact
->whereStr
= wxT("NAME = (SELECT MIN(NAME) FROM ");
1125 wxGetApp().Contact
->whereStr
+= CONTACT_TABLE_NAME
;
1126 wxGetApp().Contact
->whereStr
+= wxT(")");
1129 wxGetApp().Contact
->SetWhereClause(wxGetApp().Contact
->whereStr
.c_str());
1130 if (!wxGetApp().Contact
->Query())
1133 tStr
= wxT("ODBC error during Query()\n\n");
1134 tStr
+= GetExtendedDBErrorMsg(wxGetApp().Contact
->GetDb(),__FILE__
,__LINE__
);
1135 wxMessageBox(tStr
,wxT("ODBC Error..."),wxOK
| wxICON_EXCLAMATION
);
1138 if (!wxGetApp().Contact
->GetNext())
1139 wxGetApp().Contact
->Initialize();
1141 pResetBtn
->Enable(FALSE
);
1147 if (widgetName
== pNameListBtn
->GetName())
1149 new ClookUpDlg(/* wxWindow *parent */ this,
1150 /* wxChar *windowTitle */ wxT("Select contact name"),
1151 /* wxChar *tableName */ (wxChar
*) CONTACT_TABLE_NAME
,
1152 /* wxChar *dispCol1 */ wxT("NAME"),
1153 /* wxChar *dispCol2 */ wxT("JOINDATE"),
1154 /* wxChar *where */ wxT(""),
1155 /* wxChar *orderBy */ wxT("NAME"),
1156 /* wxDb *pDb */ wxGetApp().READONLY_DB
,
1157 /* const wxString &defDir */ wxGetApp().DbConnectInf
->GetDefaultDir(),
1158 /* bool distinctValues */ TRUE
);
1160 if (ListDB_Selection
&& wxStrlen(ListDB_Selection
))
1162 wxString w
= wxT("NAME = '");
1163 w
+= ListDB_Selection
;
1171 if (widgetName
== pDataTypesBtn
->GetName())
1173 CheckSupportForAllDataTypes(wxGetApp().READONLY_DB
);
1175 } // Data types Button
1177 if (widgetName
== pDbDiagsBtn
->GetName())
1179 DisplayDbDiagnostics(wxGetApp().READONLY_DB
);
1183 } // CeditorDlg::OnCommand()
1186 bool CeditorDlg::Initialize()
1188 // Create the data structure and a new database connection.
1189 // (As there is not a pDb being passed in the constructor, a new database
1190 // connection is created)
1191 wxGetApp().Contact
= new Ccontact();
1193 if (!wxGetApp().Contact
)
1195 wxMessageBox(wxT("Unable to instantiate an instance of Ccontact"),wxT("Error..."),wxOK
| wxICON_EXCLAMATION
);
1199 // Check if the table exists or not. If it doesn't, ask the user if they want to
1200 // create the table. Continue trying to create the table until it exists, or user aborts
1201 while (!wxGetApp().Contact
->GetDb()->TableExists((wxChar
*)CONTACT_TABLE_NAME
,
1202 wxGetApp().DbConnectInf
->GetUserID(),
1203 wxGetApp().DbConnectInf
->GetDefaultDir()))
1206 tStr
.Printf(wxT("Unable to open the table '%s'.\n\nTable may need to be created...?\n\n"),CONTACT_TABLE_NAME
);
1207 tStr
+= GetExtendedDBErrorMsg(wxGetApp().Contact
->GetDb(),__FILE__
,__LINE__
);
1208 wxMessageBox(tStr
,wxT("ODBC Error..."),wxOK
| wxICON_EXCLAMATION
);
1210 bool createTable
= (wxMessageBox(wxT("Do you wish to try to create/clear the CONTACTS table?"),wxT("Confirm"),wxYES_NO
|wxICON_QUESTION
) == wxYES
);
1218 wxGetApp().CreateDataTable(FALSE
);
1221 // Tables must be "opened" before anything other than creating/deleting table can be done
1222 if (!wxGetApp().Contact
->Open())
1224 // Table does exist, or there was some problem opening it. Currently this should
1225 // never fail, except in the case of the table not exisiting or the current
1226 // user has insufficent privileges to access the table
1228 // This code is experimenting with a new function that will hopefully be available
1229 // in the 2.4 release. This check will determine whether the open failing was due
1230 // to the table not existing, or the users privileges being insufficient to
1232 if (!wxGetApp().Contact
->GetDb()->TablePrivileges(CONTACT_TABLE_NAME
, wxT("SELECT"),
1233 wxGetApp().Contact
->GetDb()->GetUsername(),
1234 wxGetApp().Contact
->GetDb()->GetUsername(),
1235 wxGetApp().DbConnectInf
->GetDefaultDir()))
1238 tStr
.Printf(wxT("Unable to open the table '%s' (likely due to\ninsufficient privileges of the logged in user).\n\n"),CONTACT_TABLE_NAME
);
1239 tStr
+= GetExtendedDBErrorMsg(wxGetApp().Contact
->GetDb(),__FILE__
,__LINE__
);
1240 wxMessageBox(tStr
,wxT("ODBC Error..."),wxOK
| wxICON_EXCLAMATION
);
1244 if (!wxGetApp().Contact
->GetDb()->TableExists(CONTACT_TABLE_NAME
,
1245 wxGetApp().Contact
->GetDb()->GetUsername(),
1246 wxGetApp().DbConnectInf
->GetDefaultDir()))
1249 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
);
1250 tStr
+= GetExtendedDBErrorMsg(wxGetApp().Contact
->GetDb(),__FILE__
,__LINE__
);
1251 wxMessageBox(tStr
,wxT("ODBC Error..."),wxOK
| wxICON_EXCLAMATION
);
1259 (void)new wxStaticBox(this, EDITOR_DIALOG_FN_GROUP
, wxT(""), wxPoint(15, 1), wxSize(497, 69), 0, wxT("FunctionGrp"));
1260 (void)new wxStaticBox(this, EDITOR_DIALOG_SEARCH_GROUP
, wxT(""), wxPoint(417, 1), wxSize(95, 242), 0, wxT("SearchGrp"));
1262 pCreateBtn
= new wxButton(this, EDITOR_DIALOG_CREATE
, wxT("&Create"), wxPoint( 25, 21), wxSize( 70, 35), 0, wxDefaultValidator
, wxT("CreateBtn"));
1263 pEditBtn
= new wxButton(this, EDITOR_DIALOG_EDIT
, wxT("&Edit"), wxPoint(102, 21), wxSize( 70, 35), 0, wxDefaultValidator
, wxT("EditBtn"));
1264 pDeleteBtn
= new wxButton(this, EDITOR_DIALOG_DELETE
, wxT("&Delete"), wxPoint(179, 21), wxSize( 70, 35), 0, wxDefaultValidator
, wxT("DeleteBtn"));
1265 pCopyBtn
= new wxButton(this, EDITOR_DIALOG_COPY
, wxT("Cop&y"), wxPoint(256, 21), wxSize( 70, 35), 0, wxDefaultValidator
, wxT("CopyBtn"));
1266 pSaveBtn
= new wxButton(this, EDITOR_DIALOG_SAVE
, wxT("&Save"), wxPoint(333, 21), wxSize( 70, 35), 0, wxDefaultValidator
, wxT("SaveBtn"));
1267 pCancelBtn
= new wxButton(this, EDITOR_DIALOG_CANCEL
, wxT("C&ancel"), wxPoint(430, 21), wxSize( 70, 35), 0, wxDefaultValidator
, wxT("CancelBtn"));
1268 pPrevBtn
= new wxButton(this, EDITOR_DIALOG_PREV
, wxT("<< &Prev"), wxPoint(430, 81), wxSize( 70, 35), 0, wxDefaultValidator
, wxT("PrevBtn"));
1269 pNextBtn
= new wxButton(this, EDITOR_DIALOG_NEXT
, wxT("&Next >>"), wxPoint(430, 121), wxSize( 70, 35), 0, wxDefaultValidator
, wxT("NextBtn"));
1270 pQueryBtn
= new wxButton(this, EDITOR_DIALOG_QUERY
, wxT("&Query"), wxPoint(430, 161), wxSize( 70, 35), 0, wxDefaultValidator
, wxT("QueryBtn"));
1271 pResetBtn
= new wxButton(this, EDITOR_DIALOG_RESET
, wxT("&Reset"), wxPoint(430, 200), wxSize( 70, 35), 0, wxDefaultValidator
, wxT("ResetBtn"));
1272 pNameMsg
= new wxStaticText(this, EDITOR_DIALOG_NAME_MSG
, wxT("Name:"), wxPoint( 17, 80), wxSize( -1, -1), 0, wxT("NameMsg"));
1273 pNameTxt
= new wxTextCtrl(this, EDITOR_DIALOG_NAME_TEXT
, wxT(""), wxPoint( 17, 97), wxSize(308, 25), 0, wxDefaultValidator
, wxT("NameTxt"));
1274 pNameListBtn
= new wxButton(this, EDITOR_DIALOG_LOOKUP
, wxT("&Lookup"), wxPoint(333, 97), wxSize( 70, 24), 0, wxDefaultValidator
, wxT("LookupBtn"));
1275 pAddress1Msg
= new wxStaticText(this, EDITOR_DIALOG_ADDRESS1_MSG
, wxT("Address:"), wxPoint( 17, 130), wxSize( -1, -1), 0, wxT("Address1Msg"));
1276 pAddress1Txt
= new wxTextCtrl(this, EDITOR_DIALOG_ADDRESS2_TEXT
, wxT(""), wxPoint( 17, 147), wxSize(308, 25), 0, wxDefaultValidator
, wxT("Address1Txt"));
1277 pAddress2Msg
= new wxStaticText(this, EDITOR_DIALOG_ADDRESS2_MSG
, wxT("Address:"), wxPoint( 17, 180), wxSize( -1, -1), 0, wxT("Address2Msg"));
1278 pAddress2Txt
= new wxTextCtrl(this, EDITOR_DIALOG_ADDRESS2_TEXT
, wxT(""), wxPoint( 17, 197), wxSize(308, 25), 0, wxDefaultValidator
, wxT("Address2Txt"));
1279 pCityMsg
= new wxStaticText(this, EDITOR_DIALOG_CITY_MSG
, wxT("City:"), wxPoint( 17, 230), wxSize( -1, -1), 0, wxT("CityMsg"));
1280 pCityTxt
= new wxTextCtrl(this, EDITOR_DIALOG_CITY_TEXT
, wxT(""), wxPoint( 17, 247), wxSize(225, 25), 0, wxDefaultValidator
, wxT("CityTxt"));
1281 pStateMsg
= new wxStaticText(this, EDITOR_DIALOG_STATE_MSG
, wxT("State:"), wxPoint(250, 230), wxSize( -1, -1), 0, wxT("StateMsg"));
1282 pStateTxt
= new wxTextCtrl(this, EDITOR_DIALOG_STATE_TEXT
, wxT(""), wxPoint(250, 247), wxSize(153, 25), 0, wxDefaultValidator
, wxT("StateTxt"));
1283 pCountryMsg
= new wxStaticText(this, EDITOR_DIALOG_COUNTRY_MSG
, wxT("Country:"), wxPoint( 17, 280), wxSize( -1, -1), 0, wxT("CountryMsg"));
1284 pCountryTxt
= new wxTextCtrl(this, EDITOR_DIALOG_COUNTRY_TEXT
, wxT(""), wxPoint( 17, 297), wxSize(225, 25), 0, wxDefaultValidator
, wxT("CountryTxt"));
1285 pPostalCodeMsg
= new wxStaticText(this, EDITOR_DIALOG_POSTAL_MSG
, wxT("Postal Code:"),wxPoint(250, 280), wxSize( -1, -1), 0, wxT("PostalCodeMsg"));
1286 pPostalCodeTxt
= new wxTextCtrl(this, EDITOR_DIALOG_POSTAL_TEXT
, wxT(""), wxPoint(250, 297), wxSize(153, 25), 0, wxDefaultValidator
, wxT("PostalCodeTxt"));
1288 wxString choice_strings
[5];
1289 choice_strings
[0] = wxT("English");
1290 choice_strings
[1] = wxT("French");
1291 choice_strings
[2] = wxT("German");
1292 choice_strings
[3] = wxT("Spanish");
1293 choice_strings
[4] = wxT("Other");
1295 pNativeLangChoice
= new wxChoice(this, EDITOR_DIALOG_LANG_CHOICE
, wxPoint( 17, 346), wxSize(277, -1), 5, choice_strings
);
1296 pNativeLangMsg
= new wxStaticText(this, EDITOR_DIALOG_LANG_MSG
, wxT("Native language:"), wxPoint( 17, 330), wxSize( -1, -1), 0, wxT("NativeLangMsg"));
1298 wxString radio_strings
[2];
1299 radio_strings
[0] = wxT("No");
1300 radio_strings
[1] = wxT("Yes");
1301 pDeveloperRadio
= new wxRadioBox(this,EDITOR_DIALOG_DEVELOPER
, wxT("Developer:"), wxPoint(303, 330), wxSize( -1, -1), 2, radio_strings
, 2, wxHORIZONTAL
);
1302 pJoinDateMsg
= new wxStaticText(this, EDITOR_DIALOG_JOIN_MSG
, wxT("Date joined:"), wxPoint( 17, 380), wxSize( -1, -1), 0, wxT("JoinDateMsg"));
1303 pJoinDateTxt
= new wxTextCtrl(this, EDITOR_DIALOG_JOIN_TEXT
, wxT(""), wxPoint( 17, 397), wxSize(150, 25), 0, wxDefaultValidator
, wxT("JoinDateTxt"));
1304 pContribMsg
= new wxStaticText(this, EDITOR_DIALOG_CONTRIB_MSG
,wxT("Contributions:"), wxPoint(175, 380), wxSize( -1, -1), 0, wxT("ContribMsg"));
1305 pContribTxt
= new wxTextCtrl(this, EDITOR_DIALOG_CONTRIB_TEXT
, wxT(""), wxPoint(175, 397), wxSize(120, 25), 0, wxDefaultValidator
, wxT("ContribTxt"));
1306 pLinesMsg
= new wxStaticText(this, EDITOR_DIALOG_LINES_MSG
, wxT("Lines of code:"), wxPoint(303, 380), wxSize( -1, -1), 0, wxT("LinesMsg"));
1307 pLinesTxt
= new wxTextCtrl(this, EDITOR_DIALOG_LINES_TEXT
, wxT(""), wxPoint(303, 397), wxSize(100, 25), 0, wxDefaultValidator
, wxT("LinesTxt"));
1309 pDataTypesBtn
= new wxButton(this, EDITOR_DIALOG_DATATYPES
, wxT("Data&types"), wxPoint(430, 337), wxSize( 70, 35), 0, wxDefaultValidator
, wxT("DataTypesBtn"));
1310 pDbDiagsBtn
= new wxButton(this, EDITOR_DIALOG_DB_DIAGS
, wxT("DB Dia&gs"), wxPoint(430, 387), wxSize( 70, 35), 0, wxDefaultValidator
, wxT("DbDiagsBtn"));
1312 // Now that all the widgets on the panel are created, its safe to allow ::OnCommand() to
1313 // handle all widget processing
1314 widgetPtrsSet
= TRUE
;
1316 // Setup the orderBy and where clauses to return back a single record as the result set,
1317 // as there will only be one record being shown on the dialog at a time, this optimizes
1318 // network traffic by only returning a one row result
1320 wxGetApp().Contact
->SetOrderByClause(wxT("NAME")); // field name to sort by
1322 // The wxString "whereStr" is not a member of the wxDbTable object, it is a member variable
1323 // specifically in the Ccontact class. It is used here for simpler construction of a varying
1324 // length string, and then after the string is built, the wxDbTable member variable "where" is
1325 // assigned the pointer to the constructed string.
1327 // The constructed where clause below has a sub-query within it "SELECT MIN(NAME) FROM %s"
1328 // to achieve a single row (in this case the first name in alphabetical order).
1330 if (wxGetApp().Contact
->GetDb()->Dbms() != dbmsPOSTGRES
&&
1331 wxGetApp().Contact
->GetDb()->Dbms() != dbmsMY_SQL
)
1333 wxGetApp().Contact
->whereStr
.Printf(wxT("NAME = (SELECT MIN(NAME) FROM %s)"),
1334 wxGetApp().Contact
->GetTableName().c_str());
1335 // NOTE: (const wxChar*) returns a pointer which may not be valid later, so this is short term use only
1336 wxGetApp().Contact
->SetWhereClause(wxGetApp().Contact
->whereStr
);
1339 wxGetApp().Contact
->SetWhereClause(wxT(""));
1341 // Perform the Query to get the result set.
1342 // NOTE: If there are no rows returned, that is a valid result, so Query() would return TRUE.
1343 // Only if there is a database error will Query() come back as FALSE
1344 if (!wxGetApp().Contact
->Query())
1347 tStr
= wxT("ODBC error during Query()\n\n");
1348 tStr
+= GetExtendedDBErrorMsg(wxGetApp().Contact
->GetDb(),__FILE__
,__LINE__
);
1349 wxMessageBox(tStr
,wxT("ODBC Error..."),wxOK
| wxICON_EXCLAMATION
);
1353 // Since Query succeeded, now get the row that was returned
1354 if (!wxGetApp().Contact
->GetNext())
1355 // If the GetNext() failed at this point, then there are no rows to retrieve,
1356 // so clear the values in the members of "Contact" so that PutData() blanks the
1357 // widgets on the dialog
1358 wxGetApp().Contact
->Initialize();
1360 wxGetApp().Contact->GetDb()->RollbackTrans();
1369 } // CeditorDlg::Initialize()
1372 void CeditorDlg::FieldsEditable()
1377 pNameTxt
->Enable((mode
== mCreate
) || (mode
== mEdit
));
1378 pAddress1Txt
->Enable((mode
== mCreate
) || (mode
== mEdit
));
1379 pAddress2Txt
->Enable((mode
== mCreate
) || (mode
== mEdit
));
1380 pCityTxt
->Enable((mode
== mCreate
) || (mode
== mEdit
));
1381 pStateTxt
->Enable((mode
== mCreate
) || (mode
== mEdit
));
1382 pPostalCodeTxt
->Enable((mode
== mCreate
) || (mode
== mEdit
));
1383 pCountryTxt
->Enable((mode
== mCreate
) || (mode
== mEdit
));
1385 pJoinDateTxt
->Enable((mode
== mCreate
) || (mode
== mEdit
));
1386 pContribTxt
->Enable((mode
== mCreate
) || (mode
== mEdit
));
1387 pLinesTxt
->Enable((mode
== mCreate
) || (mode
== mEdit
));
1388 pNativeLangChoice
->Enable((mode
== mCreate
) || (mode
== mEdit
));
1389 pDeveloperRadio
->Enable((mode
== mCreate
) || (mode
== mEdit
));
1391 } // CeditorDlg::FieldsEditable()
1394 void CeditorDlg::SetMode(enum DialogModes m
)
1415 pCreateBtn
->Enable( !edit
);
1416 pEditBtn
->Enable( !edit
&& (wxStrcmp(wxGetApp().Contact
->Name
,wxT(""))!=0) );
1417 pDeleteBtn
->Enable( !edit
&& (wxStrcmp(wxGetApp().Contact
->Name
,wxT(""))!=0) );
1418 pCopyBtn
->Enable( !edit
&& (wxStrcmp(wxGetApp().Contact
->Name
,wxT(""))!=0) );
1419 pSaveBtn
->Enable( edit
);
1420 pCancelBtn
->Enable( edit
);
1421 pPrevBtn
->Enable( !edit
);
1422 pNextBtn
->Enable( !edit
);
1423 pQueryBtn
->Enable( !edit
);
1424 pResetBtn
->Enable( !edit
&& !wxGetApp().Contact
->qryWhereStr
.IsEmpty() );
1425 pNameListBtn
->Enable( !edit
);
1429 } // CeditorDlg::SetMode()
1432 bool CeditorDlg::PutData()
1436 pNameTxt
->SetValue(wxGetApp().Contact
->Name
);
1437 pAddress1Txt
->SetValue(wxGetApp().Contact
->Addr1
);
1438 pAddress2Txt
->SetValue(wxGetApp().Contact
->Addr2
);
1439 pCityTxt
->SetValue(wxGetApp().Contact
->City
);
1440 pStateTxt
->SetValue(wxGetApp().Contact
->State
);
1441 pCountryTxt
->SetValue(wxGetApp().Contact
->Country
);
1442 pPostalCodeTxt
->SetValue(wxGetApp().Contact
->PostalCode
);
1444 tStr
.Printf(wxT("%d/%d/%d"),wxGetApp().Contact
->JoinDate
.month
,wxGetApp().Contact
->JoinDate
.day
,wxGetApp().Contact
->JoinDate
.year
);
1445 pJoinDateTxt
->SetValue(tStr
);
1447 tStr
.Printf(wxT("%d"),wxGetApp().Contact
->Contributions
);
1448 pContribTxt
->SetValue(tStr
);
1450 tStr
.Printf(wxT("%lu"),wxGetApp().Contact
->LinesOfCode
);
1451 pLinesTxt
->SetValue(tStr
);
1453 pNativeLangChoice
->SetSelection(wxGetApp().Contact
->NativeLanguage
);
1455 pDeveloperRadio
->SetSelection(wxGetApp().Contact
->IsDeveloper
);
1458 } // Ceditor::PutData()
1462 * Reads the data out of all the widgets on the dialog. Some data evaluation is done
1463 * to ensure that there is a name entered and that the date field is valid.
1465 * A return value of TRUE means that valid data was retrieved from the dialog, otherwise
1466 * invalid data was found (and a message was displayed telling the user what to fix), and
1467 * the data was not placed into the appropraite fields of Ccontact
1469 bool CeditorDlg::GetData()
1471 // Validate that the data currently entered into the widgets is valid data
1474 tStr
= pNameTxt
->GetValue();
1475 if (!wxStrcmp((const wxChar
*) tStr
,wxT("")))
1477 wxMessageBox(wxT("A name is required for entry into the contact table"),wxT("Notice..."),wxOK
| wxICON_INFORMATION
);
1481 bool invalid
= FALSE
;
1485 tStr
= pJoinDateTxt
->GetValue();
1486 if (tStr
.Freq(wxT('/')) != 2)
1489 // Find the month, day, and year tokens
1492 first
= tStr
.First(wxT('/'));
1493 second
= tStr
.Last(wxT('/'));
1495 mm
= atoi(tStr
.SubString(0,first
));
1496 dd
= atoi(tStr
.SubString(first
+1,second
));
1497 yyyy
= atoi(tStr
.SubString(second
+1,tStr
.Length()-1));
1499 invalid
= !(mm
&& dd
&& yyyy
);
1502 // Force Year 2000 compliance
1503 if (!invalid
&& (yyyy
< 1000))
1506 // Check the token ranges for validity
1511 else if ((mm
< 1) || (mm
> 12))
1519 int days
[12] = {31,28,31,30,31,30,
1521 if (dd
> days
[mm
-1])
1524 if ((dd
== 29) && (mm
== 2))
1526 if (((yyyy
% 4) == 0) && (((yyyy
% 100) != 0) || ((yyyy
% 400) == 0)))
1536 wxGetApp().Contact
->JoinDate
.month
= mm
;
1537 wxGetApp().Contact
->JoinDate
.day
= dd
;
1538 wxGetApp().Contact
->JoinDate
.year
= yyyy
;
1542 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
);
1546 tStr
= pNameTxt
->GetValue();
1547 wxStrcpy(wxGetApp().Contact
->Name
,(const wxChar
*) tStr
);
1548 wxStrcpy(wxGetApp().Contact
->Addr1
,pAddress1Txt
->GetValue());
1549 wxStrcpy(wxGetApp().Contact
->Addr2
,pAddress2Txt
->GetValue());
1550 wxStrcpy(wxGetApp().Contact
->City
,pCityTxt
->GetValue());
1551 wxStrcpy(wxGetApp().Contact
->State
,pStateTxt
->GetValue());
1552 wxStrcpy(wxGetApp().Contact
->Country
,pCountryTxt
->GetValue());
1553 wxStrcpy(wxGetApp().Contact
->PostalCode
,pPostalCodeTxt
->GetValue());
1555 wxGetApp().Contact
->Contributions
= atoi(pContribTxt
->GetValue());
1556 wxGetApp().Contact
->LinesOfCode
= atol(pLinesTxt
->GetValue());
1558 wxGetApp().Contact
->NativeLanguage
= (enum Language
) pNativeLangChoice
->GetSelection();
1559 wxGetApp().Contact
->IsDeveloper
= pDeveloperRadio
->GetSelection() > 0;
1562 } // CeditorDlg::GetData()
1566 * Retrieve data from the dialog, verify the validity of the data, and if it is valid,
1567 * try to insert/update the data to the table based on the current 'mode' the dialog
1570 * A return value of TRUE means the insert/update was completed successfully, a return
1571 * value of FALSE means that Save() failed. If returning FALSE, then this function
1572 * has displayed a detailed error message for the user.
1574 bool CeditorDlg::Save()
1576 bool failed
= FALSE
;
1578 // Read the data in the widgets of the dialog to get the user's data
1582 // Perform any other required validations necessary before saving
1585 wxBeginBusyCursor();
1587 if (mode
== mCreate
)
1589 RETCODE result
= wxGetApp().Contact
->Insert();
1591 failed
= (result
!= DB_SUCCESS
);
1594 // Some errors may be expected, like a duplicate key, so handle those instances with
1595 // specific error messages.
1596 if (result
== DB_ERR_INTEGRITY_CONSTRAINT_VIOL
)
1599 tStr
= wxT("A duplicate key value already exists in the table.\nUnable to save record\n\n");
1600 tStr
+= GetExtendedDBErrorMsg(wxGetApp().Contact
->GetDb(),__FILE__
,__LINE__
);
1601 wxMessageBox(tStr
,wxT("ODBC Error..."),wxOK
| wxICON_EXCLAMATION
);
1605 // Some other unexpexted error occurred
1607 tStr
= wxT("Database insert failed\n\n");
1608 tStr
+= GetExtendedDBErrorMsg(wxGetApp().Contact
->GetDb(),__FILE__
,__LINE__
);
1609 wxMessageBox(tStr
,wxT("ODBC Error..."),wxOK
| wxICON_EXCLAMATION
);
1613 else // mode == mEdit
1615 wxGetApp().Contact
->whereStr
.Printf("NAME = '%s'",saveName
.c_str());
1616 if (!wxGetApp().Contact
->UpdateWhere(wxGetApp().Contact
->whereStr
))
1619 tStr
= wxT("Database update failed\n\n");
1620 tStr
+= GetExtendedDBErrorMsg(wxGetApp().Contact
->GetDb(),__FILE__
,__LINE__
);
1621 wxMessageBox(tStr
,wxT("ODBC Error..."),wxOK
| wxICON_EXCLAMATION
);
1628 wxGetApp().Contact
->GetDb()->CommitTrans();
1629 SetMode(mView
); // Sets the dialog mode back to viewing after save is successful
1632 wxGetApp().Contact
->GetDb()->RollbackTrans();
1638 } // CeditorDlg::Save()
1642 * Where this program is only showing a single row at a time in the dialog,
1643 * a special where clause must be built to find just the single row which,
1644 * in sequence, would follow the currently displayed row.
1646 bool CeditorDlg::GetNextRec()
1650 if (wxGetApp().Contact
->GetDb()->Dbms() != dbmsPOSTGRES
&&
1651 wxGetApp().Contact
->GetDb()->Dbms() != dbmsMY_SQL
)
1653 w
= wxT("NAME = (SELECT MIN(NAME) FROM ");
1654 w
+= wxGetApp().Contact
->GetTableName();
1655 w
+= wxT(" WHERE NAME > '");
1658 w
= wxT("(NAME > '");
1660 w
+= wxGetApp().Contact
->Name
;
1663 // If a query where string is currently set, append that criteria
1664 if (!wxGetApp().Contact
->qryWhereStr
.IsEmpty())
1667 w
+= wxGetApp().Contact
->qryWhereStr
;
1674 } // CeditorDlg::GetNextRec()
1678 * Where this program is only showing a single row at a time in the dialog,
1679 * a special where clause must be built to find just the single row which,
1680 * in sequence, would precede the currently displayed row.
1682 bool CeditorDlg::GetPrevRec()
1686 if (wxGetApp().Contact
->GetDb()->Dbms() != dbmsPOSTGRES
&&
1687 wxGetApp().Contact
->GetDb()->Dbms() != dbmsMY_SQL
)
1689 w
= wxT("NAME = (SELECT MAX(NAME) FROM ");
1690 w
+= wxGetApp().Contact
->GetTableName();
1691 w
+= wxT(" WHERE NAME < '");
1694 w
= wxT("(NAME < '");
1696 w
+= wxGetApp().Contact
->Name
;
1699 // If a query where string is currently set, append that criteria
1700 if (!wxGetApp().Contact
->qryWhereStr
.IsEmpty())
1703 w
+= wxGetApp().Contact
->qryWhereStr
;
1711 } // CeditorDlg::GetPrevRec()
1715 * This function is here to avoid duplicating this same code in both the
1716 * GetPrevRec() and GetNextRec() functions
1718 bool CeditorDlg::GetRec(const wxString
&whereStr
)
1720 wxGetApp().Contact
->SetWhereClause(whereStr
);
1721 wxGetApp().Contact
->SetOrderByClause(wxT("NAME"));
1723 if (!wxGetApp().Contact
->Query())
1726 tStr
= wxT("ODBC error during Query()\n\n");
1727 tStr
+= GetExtendedDBErrorMsg(wxGetApp().Contact
->GetDb(),__FILE__
,__LINE__
);
1728 wxMessageBox(tStr
,wxT("ODBC Error..."),wxOK
| wxICON_EXCLAMATION
);
1733 if (wxGetApp().Contact
->GetNext())
1740 } // CeditorDlg::GetRec()
1745 * CparameterDlg constructor
1748 BEGIN_EVENT_TABLE(CparameterDlg
, wxDialog
)
1749 EVT_BUTTON(PARAMETER_DIALOG_SAVE
, CparameterDlg::OnButton
)
1750 EVT_BUTTON(PARAMETER_DIALOG_CANCEL
, CparameterDlg::OnButton
)
1751 EVT_CLOSE(CparameterDlg::OnCloseWindow
)
1754 CparameterDlg::CparameterDlg(wxWindow
*parent
) : wxDialog (parent
, PARAMETER_DIALOG
, wxT("ODBC parameter settings"), wxPoint(-1, -1), wxSize(400, 325))
1756 // Since the ::OnCommand() function is overridden, this prevents the widget
1757 // detection in ::OnCommand() until all widgets have been initialized to prevent
1758 // uninitialized pointers from crashing the program
1759 widgetPtrsSet
= FALSE
;
1761 pParamODBCSourceMsg
= new wxStaticText(this, PARAMETER_DIALOG_SOURCE_MSG
, wxT("ODBC data sources:"), wxPoint( 10, 10), wxSize( -1, -1), 0, wxT("ParamODBCSourceMsg"));
1762 pParamODBCSourceList
= new wxListBox(this, PARAMETER_DIALOG_SOURCE_LISTBOX
, wxPoint( 10, 29), wxSize(285, 150), 0, 0, wxLB_SINGLE
|wxLB_ALWAYS_SB
, wxDefaultValidator
, wxT("ParamODBCSourceList"));
1763 pParamUserNameMsg
= new wxStaticText(this, PARAMETER_DIALOG_NAME_MSG
, wxT("Database user name:"), wxPoint( 10, 193), wxSize( -1, -1), 0, wxT("ParamUserNameMsg"));
1764 pParamUserNameTxt
= new wxTextCtrl(this, PARAMETER_DIALOG_NAME_TEXT
, wxT(""), wxPoint(10, 209), wxSize( 140, 25), 0, wxDefaultValidator
, wxT("ParamUserNameTxt"));
1765 pParamPasswordMsg
= new wxStaticText(this, PARAMETER_DIALOG_PASSWORD_MSG
, wxT("Password:"), wxPoint(156, 193), wxSize( -1, -1), 0, wxT("ParamPasswordMsg"));
1766 pParamPasswordTxt
= new wxTextCtrl(this, PARAMETER_DIALOG_PASSWORD_TEXT
, wxT(""), wxPoint(156, 209), wxSize( 140, 25), 0, wxDefaultValidator
, wxT("ParamPasswordTxt"));
1767 pParamDirPathMsg
= new wxStaticText(this, PARAMETER_DIALOG_DIRPATH_MSG
, wxT("Directory:"), wxPoint( 10, 243), wxSize( -1, -1), 0, wxT("ParamDirPathMsg"));
1768 pParamDirPathTxt
= new wxTextCtrl(this, PARAMETER_DIALOG_DIRPATH_TEXT
, wxT(""), wxPoint( 10, 259), wxSize(140, 25), 0, wxDefaultValidator
, wxT("ParamDirPathTxt"));
1769 pParamSaveBtn
= new wxButton(this, PARAMETER_DIALOG_SAVE
, wxT("&Save"), wxPoint(310, 21), wxSize( 70, 35), 0, wxDefaultValidator
, wxT("ParamSaveBtn"));
1770 pParamCancelBtn
= new wxButton(this, PARAMETER_DIALOG_CANCEL
, wxT("C&ancel"), wxPoint(310, 66), wxSize( 70, 35), 0, wxDefaultValidator
, wxT("ParamCancelBtn"));
1772 // Now that all the widgets on the panel are created, its safe to allow ::OnCommand() to
1773 // handle all widget processing
1774 widgetPtrsSet
= TRUE
;
1777 savedParamSettings
= wxGetApp().params
;
1782 } // CparameterDlg constructor
1785 void CparameterDlg::OnCloseWindow(wxCloseEvent
& event
)
1787 // Put any additional checking necessary to make certain it is alright
1788 // to close the program here that is not done elsewhere
1791 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
);
1799 wxGetApp().params
= savedParamSettings
;
1802 if (GetParent() != NULL
)
1803 GetParent()->SetFocus();
1809 SetReturnCode(0); // added so BoundsChecker would not report use of uninitialized variable
1812 } // CparameterDlg::OnCloseWindow()
1815 void CparameterDlg::OnButton( wxCommandEvent
&event
)
1817 wxWindow
*win
= (wxWindow
*) event
.GetEventObject();
1818 OnCommand( *win
, event
);
1822 void CparameterDlg::OnCommand(wxWindow
& win
, wxCommandEvent
& event
)
1824 wxString widgetName
;
1826 widgetName
= win
.GetName();
1831 if (widgetName
== pParamSaveBtn
->GetName())
1836 tStr
= wxT("Database parameters have been saved.");
1837 if (GetParent() != NULL
) // The parameter dialog was not called during startup due to a missing cfg file
1838 tStr
+= wxT("\nNew parameters will take effect the next time the program is started.");
1839 wxMessageBox(tStr
,wxT("Notice..."),wxOK
| wxICON_INFORMATION
);
1846 if (widgetName
== pParamCancelBtn
->GetName())
1851 } // CparameterDlg::OnCommand()
1854 bool CparameterDlg::PutData()
1856 // Fill the data source list box
1857 FillDataSourceList();
1859 // Fill in the fields from the params object
1860 if (wxGetApp().params
.ODBCSource
&& wxStrlen(wxGetApp().params
.ODBCSource
))
1861 pParamODBCSourceList
->SetStringSelection(wxGetApp().params
.ODBCSource
);
1862 pParamUserNameTxt
->SetValue(wxGetApp().params
.UserName
);
1863 pParamPasswordTxt
->SetValue(wxGetApp().params
.Password
);
1864 pParamDirPathTxt
->SetValue(wxGetApp().params
.DirPath
);
1866 } // CparameterDlg::PutData()
1869 bool CparameterDlg::GetData()
1872 if (pParamODBCSourceList
->GetStringSelection() != wxT(""))
1874 tStr
= pParamODBCSourceList
->GetStringSelection();
1875 if (tStr
.Length() > (sizeof(wxGetApp().params
.ODBCSource
)-1))
1878 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());
1879 wxMessageBox(errmsg
,wxT("Internal program error..."),wxOK
| wxICON_EXCLAMATION
);
1882 wxStrcpy(wxGetApp().params
.ODBCSource
, tStr
);
1887 tStr
= pParamUserNameTxt
->GetValue();
1888 if (tStr
.Length() > (sizeof(wxGetApp().params
.UserName
)-1))
1891 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());
1892 wxMessageBox(errmsg
,wxT("Internal program error..."),wxOK
| wxICON_EXCLAMATION
);
1895 wxStrcpy(wxGetApp().params
.UserName
, tStr
);
1897 tStr
= pParamPasswordTxt
->GetValue();
1898 if (tStr
.Length() > (sizeof(wxGetApp().params
.Password
)-1))
1901 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());
1902 wxMessageBox(errmsg
,wxT("Internal program error..."),wxOK
| wxICON_EXCLAMATION
);
1905 wxStrcpy(wxGetApp().params
.Password
,tStr
);
1907 tStr
= pParamDirPathTxt
->GetValue();
1908 tStr
.Replace(wxT("\\"),wxT("/"));
1909 if (tStr
.Length() > (sizeof(wxGetApp().params
.DirPath
)-1))
1912 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());
1913 wxMessageBox(errmsg
,wxT("Internal program error..."),wxOK
| wxICON_EXCLAMATION
);
1916 wxStrcpy(wxGetApp().params
.DirPath
,tStr
);
1918 } // CparameterDlg::GetData()
1921 bool CparameterDlg::Save()
1923 // Copy the current params in case user cancels changing
1924 // the params, so that we can reset them.
1927 wxGetApp().params
= savedParamSettings
;
1931 wxGetApp().WriteParamFile(wxGetApp().params
);
1934 } // CparameterDlg::Save()
1937 void CparameterDlg::FillDataSourceList()
1939 wxChar Dsn
[SQL_MAX_DSN_LENGTH
+ 1];
1941 wxStringList strList
;
1943 while (wxDbGetDataSource(wxGetApp().DbConnectInf
->GetHenv(), Dsn
,
1944 SQL_MAX_DSN_LENGTH
+1, DsDesc
, 255))
1948 strList
.Add(wxT(""));
1949 wxChar
**p
= strList
.ListToArray();
1952 for (i
= 0; wxStrlen(p
[i
]); i
++)
1953 pParamODBCSourceList
->Append(p
[i
]);
1956 } // CparameterDlg::FillDataSourceList()
1959 BEGIN_EVENT_TABLE(CqueryDlg
, wxDialog
)
1960 EVT_BUTTON(-1, CqueryDlg::OnButton
)
1961 EVT_CLOSE(CqueryDlg::OnCloseWindow
)
1965 // CqueryDlg() constructor
1966 CqueryDlg::CqueryDlg(wxWindow
*parent
, wxDb
*pDb
, wxChar
*tblName
[],
1967 const wxString
&pWhereArg
) :
1968 wxDialog (parent
, QUERY_DIALOG
, wxT("Query"), wxPoint(-1, -1), wxSize(480, 360))
1970 wxBeginBusyCursor();
1974 masterTableName
= tblName
[0];
1975 widgetPtrsSet
= FALSE
;
1978 // Initialize the WHERE clause from the string passed in
1979 pWhere
= pWhereArg
; // Save a pointer to the output buffer
1980 if (pWhere
.Length() > (unsigned int)DB_MAX_WHERE_CLAUSE_LEN
) // Check the length of the buffer passed in
1983 s
.Printf(wxT("Maximum where clause length exceeded.\nLength must be less than %d"), DB_MAX_WHERE_CLAUSE_LEN
+1);
1984 wxMessageBox(s
,wxT("Error..."),wxOK
| wxICON_EXCLAMATION
);
1989 pQueryCol1Msg
= new wxStaticText(this, QUERY_DIALOG_COL_MSG
, wxT("Column 1:"), wxPoint( 10, 10), wxSize( 69, 16), 0, wxT("QueryCol1Msg"));
1990 pQueryCol1Choice
= new wxChoice(this, QUERY_DIALOG_COL_CHOICE
, wxPoint( 10, 27), wxSize(250, 27), 0, 0, 0, wxDefaultValidator
, wxT("QueryCol1Choice"));
1991 pQueryNotMsg
= new wxStaticText(this, QUERY_DIALOG_NOT_MSG
, wxT("NOT"), wxPoint(268, 10), wxSize( -1, -1), 0, wxT("QueryNotMsg"));
1992 pQueryNotCheck
= new wxCheckBox(this, QUERY_DIALOG_NOT_CHECKBOX
, wxT(""), wxPoint(275, 37), wxSize( 20, 20), 0, wxDefaultValidator
, wxT("QueryNotCheck"));
1994 wxString choice_strings
[9];
1995 choice_strings
[0] = wxT("=");
1996 choice_strings
[1] = wxT("<");
1997 choice_strings
[2] = wxT(">");
1998 choice_strings
[3] = wxT("<=");
1999 choice_strings
[4] = wxT(">=");
2000 choice_strings
[5] = wxT("Begins");
2001 choice_strings
[6] = wxT("Contains");
2002 choice_strings
[7] = wxT("Like");
2003 choice_strings
[8] = wxT("Between");
2005 pQueryOperatorMsg
= new wxStaticText(this, QUERY_DIALOG_OP_MSG
, wxT("Operator:"), wxPoint(305, 10), wxSize( -1, -1), 0, wxT("QueryOperatorMsg"));
2006 pQueryOperatorChoice
= new wxChoice(this, QUERY_DIALOG_OP_CHOICE
, wxPoint(305, 27), wxSize( 80, 27), 9, choice_strings
, 0, wxDefaultValidator
, wxT("QueryOperatorChoice"));
2007 pQueryCol2Msg
= new wxStaticText(this, QUERY_DIALOG_COL2_MSG
, wxT("Column 2:"), wxPoint( 10, 65), wxSize( 69, 16), 0, wxT("QueryCol2Msg"));
2008 pQueryCol2Choice
= new wxChoice(this, QUERY_DIALOG_COL2_CHOICE
, wxPoint( 10, 82), wxSize(250, 27), 0, 0, 0, wxDefaultValidator
, wxT("QueryCol2Choice"));
2009 pQuerySqlWhereMsg
= new wxStaticText(this, QUERY_DIALOG_WHERE_MSG
, wxT("SQL where clause:"), wxPoint( 10, 141), wxSize( -1, -1), 0, wxT("QuerySqlWhereMsg"));
2010 pQuerySqlWhereMtxt
= new wxTextCtrl(this, QUERY_DIALOG_WHERE_TEXT
, wxT(""), wxPoint( 10, 159), wxSize(377, 134), wxTE_MULTILINE
, wxDefaultValidator
, wxT("QuerySqlWhereMtxt"));
2011 pQueryAddBtn
= new wxButton(this, QUERY_DIALOG_ADD
, wxT("&Add"), wxPoint(406, 24), wxSize( 56, 26), 0, wxDefaultValidator
, wxT("QueryAddBtn"));
2012 pQueryAndBtn
= new wxButton(this, QUERY_DIALOG_AND
, wxT("A&nd"), wxPoint(406, 58), wxSize( 56, 26), 0, wxDefaultValidator
, wxT("QueryAndBtn"));
2013 pQueryOrBtn
= new wxButton(this, QUERY_DIALOG_OR
, wxT("&Or"), wxPoint(406, 92), wxSize( 56, 26), 0, wxDefaultValidator
, wxT("QueryOrBtn"));
2014 pQueryLParenBtn
= new wxButton(this, QUERY_DIALOG_LPAREN
, wxT("("), wxPoint(406, 126), wxSize( 26, 26), 0, wxDefaultValidator
, wxT("QueryLParenBtn"));
2015 pQueryRParenBtn
= new wxButton(this, QUERY_DIALOG_RPAREN
, wxT(")"), wxPoint(436, 126), wxSize( 26, 26), 0, wxDefaultValidator
, wxT("QueryRParenBtn"));
2016 pQueryDoneBtn
= new wxButton(this, QUERY_DIALOG_DONE
, wxT("&Done"), wxPoint(406, 185), wxSize( 56, 26), 0, wxDefaultValidator
, wxT("QueryDoneBtn"));
2017 pQueryClearBtn
= new wxButton(this, QUERY_DIALOG_CLEAR
, wxT("C&lear"), wxPoint(406, 218), wxSize( 56, 26), 0, wxDefaultValidator
, wxT("QueryClearBtn"));
2018 pQueryCountBtn
= new wxButton(this, QUERY_DIALOG_COUNT
, wxT("&Count"), wxPoint(406, 252), wxSize( 56, 26), 0, wxDefaultValidator
, wxT("QueryCountBtn"));
2019 pQueryValue1Msg
= new wxStaticText(this, QUERY_DIALOG_VALUE1_MSG
, wxT("Value:"), wxPoint(277, 66), wxSize( -1, -1), 0, wxT("QueryValue1Msg"));
2020 pQueryValue1Txt
= new wxTextCtrl(this, QUERY_DIALOG_VALUE1_TEXT
, wxT(""), wxPoint(277, 83), wxSize(108, 25), 0, wxDefaultValidator
, wxT("QueryValue1Txt"));
2021 pQueryValue2Msg
= new wxStaticText(this, QUERY_DIALOG_VALUE2_MSG
, wxT("AND"), wxPoint(238, 126), wxSize( -1, -1), 0, wxT("QueryValue2Msg"));
2022 pQueryValue2Txt
= new wxTextCtrl(this, QUERY_DIALOG_VALUE2_TEXT
, wxT(""), wxPoint(277, 120), wxSize(108, 25), 0, wxDefaultValidator
, wxT("QueryValue2Txt"));
2023 pQueryHintGrp
= new wxStaticBox(this, QUERY_DIALOG_HINT_GROUP
, wxT(""), wxPoint( 10, 291), wxSize(377, 40), 0, wxT("QueryHintGrp"));
2024 pQueryHintMsg
= new wxStaticText(this, QUERY_DIALOG_HINT_MSG
, wxT(""), wxPoint( 16, 306), wxSize( -1, -1), 0, wxT("QueryHintMsg"));
2026 widgetPtrsSet
= TRUE
;
2027 // Initialize the dialog
2029 pQueryCol2Choice
->Append(wxT("VALUE -->"));
2030 colInf
= pDB
->GetColumns(tblName
);
2036 tStr
= wxT("ODBC error during GetColumns()\n\n");
2037 tStr
+= GetExtendedDBErrorMsg(pDb
,__FILE__
,__LINE__
);
2038 wxMessageBox(tStr
,wxT("ODBC Error..."),wxOK
| wxICON_EXCLAMATION
);
2043 for (i
= 0; colInf
[i
].colName
&& wxStrlen(colInf
[i
].colName
); i
++)
2045 // If there is more than one table being queried, qualify
2046 // the column names with the table name prefix.
2047 if (tblName
[1] && wxStrlen(tblName
[1]))
2049 qualName
.Printf(wxT("%s.%s"), colInf
[i
].tableName
, colInf
[i
].colName
);
2050 pQueryCol1Choice
->Append(qualName
);
2051 pQueryCol2Choice
->Append(qualName
);
2053 else // Single table query, append just the column names
2055 pQueryCol1Choice
->Append(colInf
[i
].colName
);
2056 pQueryCol2Choice
->Append(colInf
[i
].colName
);
2060 pQueryCol1Choice
->SetSelection(0);
2061 pQueryCol2Choice
->SetSelection(0);
2062 pQueryOperatorChoice
->SetSelection(0);
2064 pQueryValue2Msg
->Show(FALSE
);
2065 pQueryValue2Txt
->Show(FALSE
);
2067 pQueryHintMsg
->SetLabel(langQRY_EQ
);
2069 pQuerySqlWhereMtxt
->SetValue(pWhere
.c_str());
2073 // Display the dialog window
2076 } // CqueryDlg() constructor
2079 CqueryDlg::~CqueryDlg()
2081 } // CqueryDlg::~CqueryDlg() destructor
2084 void CqueryDlg::OnButton(wxCommandEvent
&event
)
2086 wxWindow
*win
= (wxWindow
*) event
.GetEventObject();
2087 OnCommand( *win
, event
);
2088 } // CqueryDlg::OnButton()
2091 void CqueryDlg::OnCommand(wxWindow
& win
, wxCommandEvent
& event
)
2093 // Widget pointers won't be set when the dialog is constructed.
2094 // Control is passed through this function once for each widget on
2095 // a dialog as the dialog is constructed.
2099 wxString widgetName
= win
.GetName();
2101 // Operator choice box
2102 if (widgetName
== pQueryOperatorChoice
->GetName())
2104 // Set the help text
2105 switch((qryOp
) pQueryOperatorChoice
->GetSelection())
2108 pQueryHintMsg
->SetLabel(langQRY_EQ
);
2111 pQueryHintMsg
->SetLabel(langQRY_LT
);
2114 pQueryHintMsg
->SetLabel(langQRY_GT
);
2117 pQueryHintMsg
->SetLabel(langQRY_LE
);
2120 pQueryHintMsg
->SetLabel(langQRY_GE
);
2123 pQueryHintMsg
->SetLabel(langQRY_BEGINS
);
2126 pQueryHintMsg
->SetLabel(langQRY_CONTAINS
);
2129 pQueryHintMsg
->SetLabel(langQRY_LIKE
);
2132 pQueryHintMsg
->SetLabel(langQRY_BETWEEN
);
2136 // Hide the value2 widget
2137 pQueryValue2Msg
->Show(FALSE
); // BETWEEN will show this widget
2138 pQueryValue2Txt
->Show(FALSE
); // BETWEEN will show this widget
2140 // Disable the NOT operator for <, <=, >, >=
2141 switch((qryOp
) pQueryOperatorChoice
->GetSelection())
2147 pQueryNotCheck
->SetValue(0);
2148 pQueryNotCheck
->Enable(FALSE
);
2151 pQueryNotCheck
->Enable(TRUE
);
2155 // Manipulate the dialog to handle the selected operator
2156 switch((qryOp
) pQueryOperatorChoice
->GetSelection())
2163 pQueryCol2Choice
->Enable(TRUE
);
2164 if (pQueryCol2Choice
->GetSelection()) // Column name is highlighted
2166 pQueryValue1Msg
->Show(FALSE
);
2167 pQueryValue1Txt
->Show(FALSE
);
2169 else // "Value" is highlighted
2171 pQueryValue1Msg
->Show(TRUE
);
2172 pQueryValue1Txt
->Show(TRUE
);
2173 pQueryValue1Txt
->SetFocus();
2179 pQueryCol2Choice
->SetSelection(0);
2180 pQueryCol2Choice
->Enable(FALSE
);
2181 pQueryValue1Msg
->Show(TRUE
);
2182 pQueryValue1Txt
->Show(TRUE
);
2183 pQueryValue1Txt
->SetFocus();
2186 pQueryCol2Choice
->SetSelection(0);
2187 pQueryCol2Choice
->Enable(FALSE
);
2188 pQueryValue2Msg
->Show(TRUE
);
2189 pQueryValue2Txt
->Show(TRUE
);
2190 pQueryValue1Msg
->Show(TRUE
);
2191 pQueryValue1Txt
->Show(TRUE
);
2192 pQueryValue1Txt
->SetFocus();
2198 } // Operator choice box
2201 if (widgetName
== pQueryCol2Choice
->GetName())
2203 if (pQueryCol2Choice
->GetSelection()) // Column name is highlighted
2205 pQueryValue1Msg
->Show(FALSE
);
2206 pQueryValue1Txt
->Show(FALSE
);
2208 else // "Value" is highlighted
2210 pQueryValue1Msg
->Show(TRUE
);
2211 pQueryValue1Txt
->Show(TRUE
);
2212 pQueryValue1Txt
->SetFocus();
2215 } // Column 2 choice
2218 if (widgetName
== pQueryAddBtn
->GetName())
2225 if (widgetName
== pQueryAndBtn
->GetName())
2227 AppendToWhere(wxT(" AND\n"));
2232 if (widgetName
== pQueryOrBtn
->GetName())
2234 AppendToWhere(wxT(" OR\n"));
2238 // Left Paren button
2239 if (widgetName
== pQueryLParenBtn
->GetName())
2241 AppendToWhere(wxT("("));
2243 } // Left Paren button
2245 // Right paren button
2246 if (widgetName
== pQueryRParenBtn
->GetName())
2248 AppendToWhere(wxT(")"));
2250 } // Right Paren button
2253 if (widgetName
== pQueryDoneBtn
->GetName())
2255 // Be sure the where clause will not overflow the output buffer
2256 if (wxStrlen(pQuerySqlWhereMtxt
->GetValue()) > (unsigned int)DB_MAX_WHERE_CLAUSE_LEN
)
2259 s
.Printf(wxT("Maximum where clause length exceeded.\nLength must be less than %d"), DB_MAX_WHERE_CLAUSE_LEN
+1);
2260 wxMessageBox(s
,wxT("Error..."),wxOK
| wxICON_EXCLAMATION
);
2263 // Validate the where clause for things such as matching parens
2264 if (!ValidateWhereClause())
2266 // Copy the where clause to the output buffer and exit
2267 pWhere
= pQuerySqlWhereMtxt
->GetValue();
2273 if (widgetName
== pQueryClearBtn
->GetName())
2275 bool Ok
= (wxMessageBox(wxT("Are you sure you wish to clear the Query?"),wxT("Confirm"),wxYES_NO
|wxICON_QUESTION
) == wxYES
);
2278 pQuerySqlWhereMtxt
->SetValue(wxT(""));
2283 if (widgetName
== pQueryCountBtn
->GetName())
2285 wxBeginBusyCursor();
2291 } // CqueryDlg::OnCommand
2294 void CqueryDlg::OnCloseWindow(wxCloseEvent
& event
)
2301 GetParent()->SetFocus();
2306 SetReturnCode(1); // added so BoundsChecker would not report use of uninitialized variable
2309 } // CqueryDlg::OnCloseWindow()
2312 void CqueryDlg::AppendToWhere(wxChar
*s
)
2314 wxString whereStr
= pQuerySqlWhereMtxt
->GetValue();
2316 pQuerySqlWhereMtxt
->SetValue(whereStr
);
2317 } // CqueryDlg::AppendToWhere()
2320 void CqueryDlg::ProcessAddBtn()
2322 qryOp oper
= (qryOp
) pQueryOperatorChoice
->GetSelection();
2324 // Verify that eveything is filled in correctly
2325 if (pQueryCol2Choice
->GetSelection() == 0) // "Value" is selected
2327 // Verify that value 1 is filled in
2328 if (wxStrlen(pQueryValue1Txt
->GetValue()) == 0)
2331 pQueryValue1Txt
->SetFocus();
2334 // For the BETWEEN operator, value 2 must be filled in as well
2335 if (oper
== qryOpBETWEEN
&&
2336 wxStrlen(pQueryValue2Txt
->GetValue()) == 0)
2339 pQueryValue2Txt
->SetFocus();
2344 // Build the expression and append it to the where clause window
2345 wxString s
= pQueryCol1Choice
->GetStringSelection();
2347 if (pQueryNotCheck
->GetValue() && (oper
!= qryOpEQ
))
2353 if (pQueryNotCheck
->GetValue()) // NOT box is checked
2376 s
+= wxT(" BETWEEN");
2382 int col1Idx
= pQueryCol1Choice
->GetSelection();
2385 if (colInf
[col1Idx
].sqlDataType
== SQL_VARCHAR
||
2386 oper
== qryOpBEGINS
||
2387 oper
== qryOpCONTAINS
||
2391 if (pQueryCol2Choice
->GetSelection()) // Column name
2392 s
+= pQueryCol2Choice
->GetStringSelection();
2393 else // Column 2 is a "value"
2397 if (oper
== qryOpCONTAINS
)
2399 s
+= pQueryValue1Txt
->GetValue();
2400 if (oper
== qryOpCONTAINS
|| oper
== qryOpBEGINS
)
2406 if (oper
== qryOpBETWEEN
)
2411 s
+= pQueryValue2Txt
->GetValue();
2416 AppendToWhere((wxChar
*) (const wxChar
*) s
);
2418 } // CqueryDlg::ProcessAddBtn()
2421 void CqueryDlg::ProcessCountBtn()
2423 if (!ValidateWhereClause())
2426 if (!dbTable
) // wxDbTable object needs to be created and opened
2428 dbTable
= new wxDbTable(pDB
, masterTableName
, 0, wxT(""),
2430 wxGetApp().DbConnectInf
->GetDefaultDir());
2433 wxMessageBox(wxT("Memory allocation failed creating a wxDbTable object."),wxT("Error..."),wxOK
| wxICON_EXCLAMATION
);
2436 if (!dbTable
->Open())
2439 tStr
= wxT("ODBC error during Open()\n\n");
2440 tStr
+= GetExtendedDBErrorMsg(dbTable
->GetDb(),__FILE__
,__LINE__
);
2441 wxMessageBox(tStr
,wxT("ODBC Error..."),wxOK
| wxICON_EXCLAMATION
);
2446 // Count() with WHERE clause
2449 whereStr
= pQuerySqlWhereMtxt
->GetValue();
2450 dbTable
->SetWhereClause(whereStr
.c_str());
2452 ULONG whereCnt
= dbTable
->Count();
2454 // Count() of all records in the table
2455 dbTable
->SetWhereClause(wxT(""));
2456 ULONG totalCnt
= dbTable
->Count();
2458 if (whereCnt
> 0 || totalCnt
== 0)
2461 tStr
.Printf(wxT("%lu of %lu records match the query criteria."),whereCnt
,totalCnt
);
2462 wxMessageBox(tStr
,wxT("Notice..."),wxOK
| wxICON_INFORMATION
);
2467 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
);
2468 wxMessageBox(tStr
,wxT("Notice..."),wxOK
| wxICON_INFORMATION
);
2471 // After a wxMessageBox, the focus does not necessarily return to the
2472 // window which was the focus when the message box popped up, so return
2473 // focus to the Query dialog for certain
2476 } // CqueryDlg::ProcessCountBtn()
2479 bool CqueryDlg::ValidateWhereClause()
2481 wxString where
= pQuerySqlWhereMtxt
->GetValue();
2483 if (where
.Freq(wxT('(')) != where
.Freq(wxT(')')))
2485 wxMessageBox(wxT("There are mismatched parenthesis in the constructed where clause"),wxT("Error..."),wxOK
| wxICON_EXCLAMATION
);
2488 // After a wxMessageBox, the focus does not necessarily return to the
2489 // window which was the focus when the message box popped up, so return
2490 // focus to the Query dialog for certain
2495 } // CqueryDlg::ValidateWhereClause()
2499 void DisplayDbDiagnostics(wxDb
*pDb
)
2504 s
= langDBINF_DB_NAME
;
2505 s
+= pDb
->dbInf
.dbmsName
;
2508 s
+= langDBINF_DB_VER
;
2509 s
+= pDb
->dbInf
.dbmsVer
;
2512 s
+= langDBINF_DRIVER_NAME
;
2513 s
+= pDb
->dbInf
.driverName
;
2516 s
+= langDBINF_DRIVER_ODBC_VER
;
2517 s
+= pDb
->dbInf
.odbcVer
;
2520 s
+= langDBINF_DRIVER_MGR_ODBC_VER
;
2521 s
+= pDb
->dbInf
.drvMgrOdbcVer
;
2524 s
+= langDBINF_DRIVER_VER
;
2525 s
+= pDb
->dbInf
.driverVer
;
2528 s
+= langDBINF_SERVER_NAME
;
2529 s
+= pDb
->dbInf
.serverName
;
2532 s
+= langDBINF_FILENAME
;
2533 s
+= pDb
->dbInf
.databaseName
;
2536 s
+= langDBINF_OUTER_JOINS
;
2537 s
+= pDb
->dbInf
.outerJoins
;
2540 s
+= langDBINF_STORED_PROC
;
2541 s
+= pDb
->dbInf
.procedureSupport
;
2544 if (pDb
->dbInf
.maxConnections
)
2545 t
.sprintf("%s%d\n", langDBINF_MAX_HDBC
, pDb
->dbInf
.maxConnections
);
2547 t
.sprintf("%s%s\n", langDBINF_MAX_HDBC
, langDBINF_UNLIMITED
);
2550 if (pDb
->dbInf
.maxStmts
)
2551 t
.sprintf("%s%d\n", langDBINF_MAX_HSTMT
, pDb
->dbInf
.maxStmts
);
2553 t
.sprintf("%s%s\n", langDBINF_MAX_HSTMT
, langDBINF_UNLIMITED
);
2556 s
+= langDBINF_API_LVL
;
2557 switch(pDb
->dbInf
.apiConfLvl
)
2559 case SQL_OAC_NONE
: s
+= langDBINF_NONE
; break;
2560 case SQL_OAC_LEVEL1
: s
+= langDBINF_LEVEL1
; break;
2561 case SQL_OAC_LEVEL2
: s
+= langDBINF_LEVEL2
; break;
2565 s
+= langDBINF_CLI_LVL
;
2566 switch(pDb
->dbInf
.cliConfLvl
)
2568 case SQL_OSCC_NOT_COMPLIANT
: s
+= langDBINF_NOT_COMPLIANT
; break;
2569 case SQL_OSCC_COMPLIANT
: s
+= langDBINF_COMPLIANT
; break;
2573 s
+= langDBINF_SQL_LVL
;
2574 switch(pDb
->dbInf
.sqlConfLvl
)
2576 case SQL_OSC_MINIMUM
: s
+= langDBINF_MIN_GRAMMAR
; break;
2577 case SQL_OSC_CORE
: s
+= langDBINF_CORE_GRAMMAR
; break;
2578 case SQL_OSC_EXTENDED
: s
+= langDBINF_EXT_GRAMMAR
; break;
2582 s
+= langDBINF_COMMIT_BEHAVIOR
;
2583 switch(pDb
->dbInf
.cursorCommitBehavior
)
2585 case SQL_CB_DELETE
: s
+= langDBINF_DELETE_CURSORS
; break;
2586 case SQL_CB_CLOSE
: s
+= langDBINF_CLOSE_CURSORS
; break;
2587 case SQL_CB_PRESERVE
: s
+= langDBINF_PRESERVE_CURSORS
; break;
2591 s
+= langDBINF_ROLLBACK_BEHAVIOR
;
2592 switch(pDb
->dbInf
.cursorRollbackBehavior
)
2594 case SQL_CB_DELETE
: s
+= langDBINF_DELETE_CURSORS
; break;
2595 case SQL_CB_CLOSE
: s
+= langDBINF_CLOSE_CURSORS
; break;
2596 case SQL_CB_PRESERVE
: s
+= langDBINF_PRESERVE_CURSORS
; break;
2600 s
+= langDBINF_SUPP_NOT_NULL
;
2601 switch(pDb
->dbInf
.supportNotNullClause
)
2603 case SQL_NNC_NULL
: s
+= langNO
; break;
2604 case SQL_NNC_NON_NULL
: s
+= langYES
; break;
2608 s
+= langDBINF_SUPP_IEF
;
2609 s
+= pDb
->dbInf
.supportIEF
;
2612 // DEFAULT setting for "Transaction Isolation Level"
2613 s
+= langDBINF_TXN_ISOLATION
;
2614 switch(pDb
->dbInf
.txnIsolation
)
2616 case SQL_TXN_READ_UNCOMMITTED
: s
+= langDBINF_READ_UNCOMMITTED
; break;
2617 case SQL_TXN_READ_COMMITTED
: s
+= langDBINF_READ_COMMITTED
; break;
2618 case SQL_TXN_REPEATABLE_READ
: s
+= langDBINF_REPEATABLE_READ
; break;
2619 case SQL_TXN_SERIALIZABLE
: s
+= langDBINF_SERIALIZABLE
; break;
2621 case SQL_TXN_VERSIONING
: s
+= langDBINF_VERSIONING
; break;
2626 // CURRENT setting for "Transaction Isolation Level"
2628 s
+= langDBINF_TXN_ISOLATION_CURR
;
2629 if (SQLGetConnectOption(pDb
->GetHDBC(),SQL_TXN_ISOLATION
,&txnIsoLvl
) == SQL_SUCCESS
)
2633 case SQL_TXN_READ_UNCOMMITTED
: s
+= langDBINF_READ_UNCOMMITTED
; break;
2634 case SQL_TXN_READ_COMMITTED
: s
+= langDBINF_READ_COMMITTED
; break;
2635 case SQL_TXN_REPEATABLE_READ
: s
+= langDBINF_REPEATABLE_READ
; break;
2636 case SQL_TXN_SERIALIZABLE
: s
+= langDBINF_SERIALIZABLE
; break;
2638 case SQL_TXN_VERSIONING
: s
+= langDBINF_VERSIONING
; break;
2645 s
+= langDBINF_TXN_ISOLATION_OPTS
;
2646 if (pDb
->dbInf
.txnIsolationOptions
& SQL_TXN_READ_UNCOMMITTED
)
2647 {s
+= langDBINF_READ_UNCOMMITTED
; comma
++;}
2648 if (pDb
->dbInf
.txnIsolationOptions
& SQL_TXN_READ_COMMITTED
)
2649 {if (comma
++) s
+= ", "; s
+= langDBINF_READ_COMMITTED
;}
2650 if (pDb
->dbInf
.txnIsolationOptions
& SQL_TXN_REPEATABLE_READ
)
2651 {if (comma
++) s
+= ", "; s
+= langDBINF_REPEATABLE_READ
;}
2652 if (pDb
->dbInf
.txnIsolationOptions
& SQL_TXN_SERIALIZABLE
)
2653 {if (comma
++) s
+= ", "; s
+= langDBINF_SERIALIZABLE
;}
2655 if (pDb
->dbInf
.txnIsolationOptions
& SQL_TXN_VERSIONING
)
2656 {if (comma
++) s
+= ", "; s
+= langDBINF_VERSIONING
;}
2661 s
+= langDBINF_FETCH_DIRS
;
2662 if (pDb
->dbInf
.fetchDirections
& SQL_FD_FETCH_NEXT
)
2663 {s
+= langDBINF_NEXT
; comma
++;}
2664 if (pDb
->dbInf
.fetchDirections
& SQL_FD_FETCH_PRIOR
)
2665 {if (comma
++) s
+= ", "; s
+= langDBINF_PREV
;}
2666 if (pDb
->dbInf
.fetchDirections
& SQL_FD_FETCH_FIRST
)
2667 {if (comma
++) s
+= ", "; s
+= langDBINF_FIRST
;}
2668 if (pDb
->dbInf
.fetchDirections
& SQL_FD_FETCH_LAST
)
2669 {if (comma
++) s
+= ", "; s
+= langDBINF_LAST
;}
2670 if (pDb
->dbInf
.fetchDirections
& SQL_FD_FETCH_ABSOLUTE
)
2671 {if (comma
++) s
+= ", "; s
+= langDBINF_ABSOLUTE
;}
2672 if (pDb
->dbInf
.fetchDirections
& SQL_FD_FETCH_RELATIVE
)
2673 {if (comma
++) s
+= ", "; s
+= langDBINF_RELATIVE
;}
2675 if (pDb
->dbInf
.fetchDirections
& SQL_FD_FETCH_RESUME
)
2676 {if (comma
++) s
+= ", "; s
+= langDBINF_RESUME
;}
2678 if (pDb
->dbInf
.fetchDirections
& SQL_FD_FETCH_BOOKMARK
)
2679 {if (comma
++) s
+= ", "; s
+= langDBINF_BOOKMARK
;}
2683 s
+= langDBINF_LOCK_TYPES
;
2684 if (pDb
->dbInf
.lockTypes
& SQL_LCK_NO_CHANGE
)
2685 {s
+= langDBINF_NO_CHANGE
; comma
++;}
2686 if (pDb
->dbInf
.lockTypes
& SQL_LCK_EXCLUSIVE
)
2687 {if (comma
++) s
+= ", "; s
+= langDBINF_EXCLUSIVE
;}
2688 if (pDb
->dbInf
.lockTypes
& SQL_LCK_UNLOCK
)
2689 {if (comma
++) s
+= ", "; s
+= langDBINF_UNLOCK
;}
2693 s
+= langDBINF_POS_OPERS
;
2694 if (pDb
->dbInf
.posOperations
& SQL_POS_POSITION
)
2695 {s
+= langDBINF_POSITION
; comma
++;}
2696 if (pDb
->dbInf
.posOperations
& SQL_POS_REFRESH
)
2697 {if (comma
++) s
+= ", "; s
+= langDBINF_REFRESH
;}
2698 if (pDb
->dbInf
.posOperations
& SQL_POS_UPDATE
)
2699 {if (comma
++) s
+= ", "; s
+= langDBINF_UPD
;}
2700 if (pDb
->dbInf
.posOperations
& SQL_POS_DELETE
)
2701 {if (comma
++) s
+= ", "; s
+= langDBINF_DEL
;}
2702 if (pDb
->dbInf
.posOperations
& SQL_POS_ADD
)
2703 {if (comma
++) s
+= ", "; s
+= langDBINF_ADD
;}
2707 s
+= langDBINF_POS_STMTS
;
2708 if (pDb
->dbInf
.posStmts
& SQL_PS_POSITIONED_DELETE
)
2709 {s
+= langDBINF_POS_DEL
; comma
++;}
2710 if (pDb
->dbInf
.posStmts
& SQL_PS_POSITIONED_UPDATE
)
2711 {if (comma
++) s
+= ", "; s
+= langDBINF_POS_UPD
;}
2712 if (pDb
->dbInf
.posStmts
& SQL_PS_SELECT_FOR_UPDATE
)
2713 {if (comma
++) s
+= ", "; s
+= langDBINF_SELECT_FOR_UPD
;}
2717 s
+= langDBINF_SCROLL_CONCURR
;
2718 if (pDb
->dbInf
.scrollConcurrency
& SQL_SCCO_READ_ONLY
)
2719 {s
+= langDBINF_READ_ONLY
; comma
++;}
2720 if (pDb
->dbInf
.scrollConcurrency
& SQL_SCCO_LOCK
)
2721 {if (comma
++) s
+= ", "; s
+= langDBINF_LOCK
;}
2722 if (pDb
->dbInf
.scrollConcurrency
& SQL_SCCO_OPT_ROWVER
)
2723 {if (comma
++) s
+= ", "; s
+= langDBINF_OPT_ROWVER
;}
2724 if (pDb
->dbInf
.scrollConcurrency
& SQL_SCCO_OPT_VALUES
)
2725 {if (comma
++) s
+= ", "; s
+= langDBINF_OPT_VALUES
;}
2729 s
+= langDBINF_SCROLL_OPTS
;
2730 if (pDb
->dbInf
.scrollOptions
& SQL_SO_FORWARD_ONLY
)
2731 {s
+= langDBINF_FWD_ONLY
; comma
++;}
2732 if (pDb
->dbInf
.scrollOptions
& SQL_SO_STATIC
)
2733 {if (comma
++) s
+= ", "; s
+= langDBINF_STATIC
;}
2734 if (pDb
->dbInf
.scrollOptions
& SQL_SO_KEYSET_DRIVEN
)
2735 {if (comma
++) s
+= ", "; s
+= langDBINF_KEYSET_DRIVEN
;}
2736 if (pDb
->dbInf
.scrollOptions
& SQL_SO_DYNAMIC
)
2737 {if (comma
++) s
+= ", "; s
+= langDBINF_DYNAMIC
;}
2738 if (pDb
->dbInf
.scrollOptions
& SQL_SO_MIXED
)
2739 {if (comma
++) s
+= ", "; s
+= langDBINF_MIXED
;}
2743 s
+= langDBINF_STATIC_SENS
;
2744 if (pDb
->dbInf
.staticSensitivity
& SQL_SS_ADDITIONS
)
2745 {s
+= langDBINF_ADDITIONS
; comma
++;}
2746 if (pDb
->dbInf
.staticSensitivity
& SQL_SS_DELETIONS
)
2747 {if (comma
++) s
+= ", "; s
+= langDBINF_DELETIONS
;}
2748 if (pDb
->dbInf
.staticSensitivity
& SQL_SS_UPDATES
)
2749 {if (comma
++) s
+= ", "; s
+= langDBINF_UPDATES
;}
2753 s
+= langDBINF_TXN_CAPABLE
;
2754 switch(pDb
->dbInf
.txnCapable
)
2756 case SQL_TC_NONE
: s
+= langNO
; break;
2757 case SQL_TC_DML
: s
+= langDBINF_DML_ONLY
; break;
2758 case SQL_TC_DDL_COMMIT
: s
+= langDBINF_DDL_COMMIT
; break;
2759 case SQL_TC_DDL_IGNORE
: s
+= langDBINF_DDL_IGNORE
; break;
2760 case SQL_TC_ALL
: s
+= langDBINF_DDL_AND_DML
; break;
2764 t
.sprintf("%s%d\n", langDBINF_LOGIN_TIMEOUT
, pDb
->dbInf
.loginTimeout
);
2767 // Oracle specific information
2768 if (pDb
->Dbms() == dbmsORACLE
)
2771 s
+= langDBINF_ORACLE_BANNER
;
2774 // Oracle cache hit ratio
2777 pDb
->ExecSql("SELECT VALUE FROM V$SYSSTAT WHERE NAME = 'db block gets'");
2779 if (pDb
->GetData(1, SQL_C_ULONG
, &dbBlockGets
, 0, &cb
))
2781 t
.sprintf("%s: %lu\n", langDBINF_DB_BLOCK_GETS
, dbBlockGets
);
2785 ULONG consistentGets
;
2786 pDb
->ExecSql("SELECT VALUE FROM V$SYSSTAT WHERE NAME = 'consistent gets'");
2788 if (pDb
->GetData(1, SQL_C_ULONG
, &consistentGets
, 0, &cb
))
2790 t
.sprintf("%s: %lu\n", langDBINF_CONSISTENT_GETS
, consistentGets
);
2795 pDb
->ExecSql("SELECT VALUE FROM V$SYSSTAT WHERE NAME = 'physical reads'");
2797 if (pDb
->GetData(1, SQL_C_ULONG
, &physReads
, 0, &cb
))
2799 t
.sprintf("%s: %lu\n", langDBINF_PHYSICAL_READS
, physReads
);
2803 ULONG hitRatio
= (ULONG
)((1.00 - ((float)physReads
/ (float)(dbBlockGets
+ consistentGets
))) * 100.00);
2804 t
.sprintf("*** %s: %lu%%\n", langDBINF_CACHE_HIT_RATIO
, hitRatio
);
2807 // Tablespace information
2809 s
+= langDBINF_TABLESPACE_IO
;
2812 char tablespaceName
[257];
2813 pDb
->ExecSql("SELECT NAME,PHYRDS,PHYWRTS FROM V$DATAFILE, V$FILESTAT WHERE V$DATAFILE.FILE# = V$FILESTAT.FILE#");
2814 while (pDb
->GetNext())
2816 pDb
->GetData(1, SQL_C_CHAR
, tablespaceName
, 257, &cb
);
2817 pDb
->GetData(2, SQL_C_ULONG
, &physReads
, 0, &cb
);
2818 pDb
->GetData(3, SQL_C_ULONG
, &physWrites
, 0, &cb
);
2819 t
.sprintf("%s\n\t%s: %lu\t%s: %lu\n", tablespaceName
,
2820 langDBINF_PHYSICAL_READS
, physReads
, langDBINF_PHYSICAL_WRITES
, physWrites
);
2829 } // DisplayDbDiagnostics()
2835 TEST CODE FOR TESTING THE wxDbCreateDataSource() FUNCTION
2838 result = wxDbCreateDataSource(wxT("Microsoft Access Driver (*.mdb)"),wxT("GLT-TEST2"),wxT("GLT-Descrip"),FALSE,wxT(""),this);
2841 // check for errors caused by ConfigDSN based functions
2844 wxChar errMsg[500+1];
2845 errMsg[0] = wxT('\0');
2847 SQLInstallerError(1,&retcode,errMsg,500,&cb);
2849 wxMessageBox(wxT("FAILED creating data source"),wxT("FAILED"));
2852 wxMessageBox(wxT("SUCCEEDED creating data source"),wxT("SUCCESS"));