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 */
59 #error Sample cannot be compiled unless setup.h has wxUSE_ODBC set to 1
63 const char *GetExtendedDBErrorMsg(wxDb
*pDb
, char *ErrFile
, int ErrLine
)
70 if (ErrFile
|| ErrLine
)
74 msg
+= wxT(" Line: ");
75 tStr
.Printf(wxT("%d"),ErrLine
);
80 msg
.Append (wxT("\nODBC errors:\n"));
83 // Display errors for this connection
85 for (i
= 0; i
< DB_MAX_ERROR_HISTORY
; i
++)
87 if (pDb
->errorList
[i
])
89 msg
.Append(pDb
->errorList
[i
]);
90 if (wxStrcmp(pDb
->errorList
[i
],wxT("")) != 0)
91 msg
.Append(wxT("\n"));
92 // Clear the errmsg buffer so the next error will not
93 // end up showing the previous error that have occurred
94 wxStrcpy(pDb
->errorList
[i
],wxT(""));
100 } // GetExtendedDBErrorMsg
103 bool DataTypeSupported(wxDb
*pDb
, SWORD datatype
)
105 wxDbSqlTypeInfo sqlTypeInfo
;
107 bool breakpoint
= FALSE
;
109 if (pDb
->GetDataTypeInfo(datatype
, sqlTypeInfo
))
114 } // GetDataTypesSupported();
118 void CheckSupportForAllDataTypes(wxDb
*pDb
)
120 wxLogMessage("\nThe following datatypes are supported by the\ndatabase you are currently connected to:");
122 if (DataTypeSupported(pDb
,SQL_C_BINARY
))
123 wxLogMessage("SQL_C_BINARY");
126 if (DataTypeSupported(pDb
,SQL_C_BIT
))
127 wxLogMessage("SQL_C_BIT");
129 #ifdef SQL_C_BOOKMARK
130 if (DataTypeSupported(pDb
,SQL_C_BOOKMARK
))
131 wxLogMessage("SQL_C_BOOKMARK");
134 if (DataTypeSupported(pDb
,SQL_C_CHAR
))
135 wxLogMessage("SQL_C_CHAR");
138 if (DataTypeSupported(pDb
,SQL_C_DATE
))
139 wxLogMessage("SQL_C_DATE");
142 if (DataTypeSupported(pDb
,SQL_C_DEFAULT
))
143 wxLogMessage("SQL_C_DEFAULT");
146 if (DataTypeSupported(pDb
,SQL_C_DOUBLE
))
147 wxLogMessage("SQL_C_DOUBLE");
150 if (DataTypeSupported(pDb
,SQL_C_FLOAT
))
151 wxLogMessage("SQL_C_FLOAT");
154 if (DataTypeSupported(pDb
,SQL_C_GUID
))
155 wxLogMessage("SQL_C_GUID");
157 #ifdef SQL_C_INTERVAL_DAY
158 if (DataTypeSupported(pDb
,SQL_C_INTERVAL_DAY
))
159 wxLogMessage("SQL_C_INTERVAL_DAY");
161 #ifdef SQL_C_INTERVAL_DAY_TO_HOUR
162 if (DataTypeSupported(pDb
,SQL_C_INTERVAL_DAY_TO_HOUR
))
163 wxLogMessage("SQL_C_INTERVAL_DAY_TO_HOUR");
165 #ifdef SQL_C_INTERVAL_DAY_TO_MINUTE
166 if (DataTypeSupported(pDb
,SQL_C_INTERVAL_DAY_TO_MINUTE
))
167 wxLogMessage("SQL_C_INTERVAL_DAY_TO_MINUTE");
169 #ifdef SQL_C_INTERVAL_DAY_TO_SECOND
170 if (DataTypeSupported(pDb
,SQL_C_INTERVAL_DAY_TO_SECOND
))
171 wxLogMessage("SQL_C_INTERVAL_DAY_TO_SECOND");
173 #ifdef SQL_C_INTERVAL_HOUR
174 if (DataTypeSupported(pDb
,SQL_C_INTERVAL_HOUR
))
175 wxLogMessage("SQL_C_INTERVAL_HOUR");
177 #ifdef SQL_C_INTERVAL_HOUR_TO_MINUTE
178 if (DataTypeSupported(pDb
,SQL_C_INTERVAL_HOUR_TO_MINUTE
))
179 wxLogMessage("SQL_C_INTERVAL_HOUR_TO_MINUTE");
181 #ifdef SQL_C_INTERVAL_HOUR_TO_SECOND
182 if (DataTypeSupported(pDb
,SQL_C_INTERVAL_HOUR_TO_SECOND
))
183 wxLogMessage("SQL_C_INTERVAL_HOUR_TO_SECOND");
185 #ifdef SQL_C_INTERVAL_MINUTE
186 if (DataTypeSupported(pDb
,SQL_C_INTERVAL_MINUTE
))
187 wxLogMessage("SQL_C_INTERVAL_MINUTE");
189 #ifdef SQL_C_INTERVAL_MINUTE_TO_SECOND
190 if (DataTypeSupported(pDb
,SQL_C_INTERVAL_MINUTE_TO_SECOND
))
191 wxLogMessage("SQL_C_INTERVAL_MINUTE_TO_SECOND");
193 #ifdef SQL_C_INTERVAL_MONTH
194 if (DataTypeSupported(pDb
,SQL_C_INTERVAL_MONTH
))
195 wxLogMessage("SQL_C_INTERVAL_MONTH");
197 #ifdef SQL_C_INTERVAL_SECOND
198 if (DataTypeSupported(pDb
,SQL_C_INTERVAL_SECOND
))
199 wxLogMessage("SQL_C_INTERVAL_SECOND");
201 #ifdef SQL_C_INTERVAL_YEAR
202 if (DataTypeSupported(pDb
,SQL_C_INTERVAL_YEAR
))
203 wxLogMessage("SQL_C_INTERVAL_YEAR");
205 #ifdef SQL_C_INTERVAL_YEAR_TO_MONTH
206 if (DataTypeSupported(pDb
,SQL_C_INTERVAL_YEAR_TO_MONTH
))
207 wxLogMessage("SQL_C_INTERVAL_YEAR_TO_MONTH");
210 if (DataTypeSupported(pDb
,SQL_C_LONG
))
211 wxLogMessage("SQL_C_LONG");
214 if (DataTypeSupported(pDb
,SQL_C_NUMERIC
))
215 wxLogMessage("SQL_C_NUMERIC");
218 if (DataTypeSupported(pDb
,SQL_C_SBIGINT
))
219 wxLogMessage("SQL_C_SBIGINT");
222 if (DataTypeSupported(pDb
,SQL_C_SHORT
))
223 wxLogMessage("SQL_C_SHORT");
226 if (DataTypeSupported(pDb
,SQL_C_SLONG
))
227 wxLogMessage("SQL_C_SLONG");
230 if (DataTypeSupported(pDb
,SQL_C_SSHORT
))
231 wxLogMessage("SQL_C_SSHORT");
233 #ifdef SQL_C_STINYINT
234 if (DataTypeSupported(pDb
,SQL_C_STINYINT
))
235 wxLogMessage("SQL_C_STINYINT");
238 if (DataTypeSupported(pDb
,SQL_C_TIME
))
239 wxLogMessage("SQL_C_TIME");
241 #ifdef SQL_C_TIMESTAMP
242 if (DataTypeSupported(pDb
,SQL_C_TIMESTAMP
))
243 wxLogMessage("SQL_C_TIMESTAMP");
246 if (DataTypeSupported(pDb
,SQL_C_TINYINT
))
247 wxLogMessage("SQL_C_TINYINT");
249 #ifdef SQL_C_TYPE_DATE
250 if (DataTypeSupported(pDb
,SQL_C_TYPE_DATE
))
251 wxLogMessage("SQL_C_TYPE_DATE");
253 #ifdef SQL_C_TYPE_TIME
254 if (DataTypeSupported(pDb
,SQL_C_TYPE_TIME
))
255 wxLogMessage("SQL_C_TYPE_TIME");
257 #ifdef SQL_C_TYPE_TIMESTAMP
258 if (DataTypeSupported(pDb
,SQL_C_TYPE_TIMESTAMP
))
259 wxLogMessage("SQL_C_TYPE_TIMESTAMP");
262 if (DataTypeSupported(pDb
,SQL_C_UBIGINT
))
263 wxLogMessage("SQL_C_UBIGINT");
266 if (DataTypeSupported(pDb
,SQL_C_ULONG
))
267 wxLogMessage("SQL_C_ULONG");
270 if (DataTypeSupported(pDb
,SQL_C_USHORT
))
271 wxLogMessage("SQL_C_USHORT");
273 #ifdef SQL_C_UTINYINT
274 if (DataTypeSupported(pDb
,SQL_C_UTINYINT
))
275 wxLogMessage("SQL_C_UTINYINT");
277 #ifdef SQL_C_VARBOOKMARK
278 if (DataTypeSupported(pDb
,SQL_C_VARBOOKMARK
))
279 wxLogMessage("SQL_C_VARBOOKMARK");
282 // Extended SQL types
284 if (DataTypeSupported(pDb
,SQL_DATE
))
285 wxLogMessage("SQL_DATE");
288 if (DataTypeSupported(pDb
,SQL_INTERVAL
))
289 wxLogMessage("SQL_INTERVAL");
292 if (DataTypeSupported(pDb
,SQL_TIME
))
293 wxLogMessage("SQL_TIME");
296 if (DataTypeSupported(pDb
,SQL_TIMESTAMP
))
297 wxLogMessage("SQL_TIMESTAMP");
299 #ifdef SQL_LONGVARCHAR
300 if (DataTypeSupported(pDb
,SQL_LONGVARCHAR
))
301 wxLogMessage("SQL_LONGVARCHAR");
304 if (DataTypeSupported(pDb
,SQL_BINARY
))
305 wxLogMessage("SQL_BINARY");
308 if (DataTypeSupported(pDb
,SQL_VARBINARY
))
309 wxLogMessage("SQL_VARBINARY");
311 #ifdef SQL_LONGVARBINARY
312 if (DataTypeSupported(pDb
,SQL_LONGVARBINARY
))
313 wxLogMessage("SQL_LONGVARBINARY");
316 if (DataTypeSupported(pDb
,SQL_BIGINT
))
317 wxLogMessage("SQL_BIGINT");
320 if (DataTypeSupported(pDb
,SQL_TINYINT
))
321 wxLogMessage("SQL_TINYINT");
324 if (DataTypeSupported(pDb
,SQL_BIT
))
325 wxLogMessage("SQL_BIT");
328 if (DataTypeSupported(pDb
,SQL_GUID
))
329 wxLogMessage("SQL_GUID");
333 if (DataTypeSupported(pDb
,SQL_CHAR
))
334 wxLogMessage("SQL_CHAR");
337 if (DataTypeSupported(pDb
,SQL_INTEGER
))
338 wxLogMessage("SQL_INTEGER");
341 if (DataTypeSupported(pDb
,SQL_SMALLINT
))
342 wxLogMessage("SQL_SMALLINT");
345 if (DataTypeSupported(pDb
,SQL_REAL
))
346 wxLogMessage("SQL_REAL");
349 if (DataTypeSupported(pDb
,SQL_DOUBLE
))
350 wxLogMessage("SQL_DOUBLE");
353 if (DataTypeSupported(pDb
,SQL_NUMERIC
))
354 wxLogMessage("SQL_NUMERIC");
357 if (DataTypeSupported(pDb
,SQL_DATE
))
358 wxLogMessage("SQL_DATE");
361 if (DataTypeSupported(pDb
,SQL_TIME
))
362 wxLogMessage("SQL_TIME");
365 if (DataTypeSupported(pDb
,SQL_TIMESTAMP
))
366 wxLogMessage("SQL_TIMESTAMP");
369 if (DataTypeSupported(pDb
,SQL_VARCHAR
))
370 wxLogMessage("SQL_VARCHAR");
375 if (DataTypeSupported(pDb
,SQL_C_TCHAR
))
376 wxLogMessage("SQL_C_TCHAR (Unicode support is possible)");
380 } // CheckSupportForAllDataTypes()
383 bool DatabaseDemoApp::OnInit()
388 // Create the main frame window
389 DemoFrame
= new DatabaseDemoFrame(NULL
, wxT("wxWindows Database Demo"), wxPoint(50, 50), wxSize(537, 480));
392 DemoFrame
->SetIcon(wxICON(db
));
395 wxMenu
*file_menu
= new wxMenu
;
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"));
401 wxMenu
*edit_menu
= new wxMenu
;
402 edit_menu
->Append(EDIT_PARAMETERS
, wxT("&Parameters..."));
404 wxMenu
*help_menu
= new wxMenu
;
405 help_menu
->Append(HELP_ABOUT
, wxT("&About"));
407 wxMenuBar
*menu_bar
= new wxMenuBar
;
408 menu_bar
->Append(file_menu
, wxT("&File"));
409 menu_bar
->Append(edit_menu
, wxT("&Edit"));
410 menu_bar
->Append(help_menu
, wxT("&Help"));
411 DemoFrame
->SetMenuBar(menu_bar
);
413 params
.ODBCSource
[0] = 0;
414 params
.UserName
[0] = 0;
415 params
.Password
[0] = 0;
416 params
.DirPath
[0] = 0;
419 DemoFrame
->Show(TRUE
);
421 // Passing NULL for the SQL environment handle causes
422 // the wxDbConnectInf constructor to obtain a handle
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
);
431 if (!DbConnectInf
|| !DbConnectInf
->GetHenv())
433 wxMessageBox(wxT("Unable to define data source connection info."), wxT("DB CONNECTION ERROR..."),wxOK
| wxICON_EXCLAMATION
);
434 wxDELETE(DbConnectInf
);
437 if (!ReadParamFile(params
))
438 DemoFrame
->BuildParameterDialog(NULL
);
440 if (!wxStrlen(params
.ODBCSource
))
442 wxDELETE(DbConnectInf
);
446 DbConnectInf
->SetDsn(params
.ODBCSource
);
447 DbConnectInf
->SetUserID(params
.UserName
);
448 DbConnectInf
->SetPassword(params
.Password
);
449 DbConnectInf
->SetDefaultDir(params
.DirPath
);
451 READONLY_DB
= wxDbGetConnection(DbConnectInf
);
452 if (READONLY_DB
== 0)
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
);
456 wxDELETE(DbConnectInf
);
457 wxMessageBox(wxT("Now exiting program.\n\nRestart program to try any new settings."),wxT("Notice..."),wxOK
| wxICON_INFORMATION
);
461 DemoFrame
->BuildEditorDialog();
464 DemoFrame
->Refresh();
467 } // DatabaseDemoApp::OnInit()
470 bool DatabaseDemoApp::ReadParamFile(Cparameters
¶ms
)
473 if ((paramFile
= fopen(PARAM_FILENAME
, wxT("r"))) == NULL
)
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
);
477 wxMessageBox(tStr
,wxT("File I/O Error..."),wxOK
| wxICON_EXCLAMATION
);
482 wxChar buffer
[1000+1];
483 fgets(buffer
, sizeof(params
.ODBCSource
), paramFile
);
484 buffer
[wxStrlen(buffer
)-1] = wxT('\0');
485 wxStrcpy(params
.ODBCSource
,buffer
);
487 fgets(buffer
, sizeof(params
.UserName
), paramFile
);
488 buffer
[wxStrlen(buffer
)-1] = wxT('\0');
489 wxStrcpy(params
.UserName
,buffer
);
491 fgets(buffer
, sizeof(params
.Password
), paramFile
);
492 buffer
[wxStrlen(buffer
)-1] = wxT('\0');
493 wxStrcpy(params
.Password
,buffer
);
495 fgets(buffer
, sizeof(params
.DirPath
), paramFile
);
496 buffer
[wxStrlen(buffer
)-1] = wxT('\0');
497 wxStrcpy(params
.DirPath
,buffer
);
502 } // DatabaseDemoApp::ReadParamFile()
505 bool DatabaseDemoApp::WriteParamFile(Cparameters
¶ms
)
508 if ((paramFile
= fopen(PARAM_FILENAME
, wxT("wt"))) == NULL
)
511 tStr
.Printf(wxT("Unable to write/overwrite '%s'."),PARAM_FILENAME
);
512 wxMessageBox(tStr
,wxT("File I/O Error..."),wxOK
| wxICON_EXCLAMATION
);
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
);
527 } // DatabaseDemoApp::WriteParamFile()
530 void DatabaseDemoApp::CreateDataTable(bool 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
);
543 Contact
->GetDb()->RollbackTrans(); // Make sure the current cursor is in a known/stable state
545 if (!Contact
->CreateTable(recreate
))
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
);
556 if (!Contact
->CreateIndexes())
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
);
570 wxMessageBox(wxT("Table and index(es) were successfully created."),wxT("Notice..."),wxOK
| wxICON_INFORMATION
);
571 } // DatabaseDemoApp::CreateDataTable()
574 BEGIN_EVENT_TABLE(DatabaseDemoFrame
, wxFrame
)
575 EVT_MENU(FILE_CREATE
, DatabaseDemoFrame::OnCreate
)
576 EVT_MENU(FILE_RECREATE_TABLE
, DatabaseDemoFrame::OnRecreateTable
)
577 EVT_MENU(FILE_RECREATE_INDEXES
, DatabaseDemoFrame::OnRecreateIndexes
)
578 EVT_MENU(FILE_EXIT
, DatabaseDemoFrame::OnExit
)
579 EVT_MENU(EDIT_PARAMETERS
, DatabaseDemoFrame::OnEditParameters
)
580 EVT_MENU(HELP_ABOUT
, DatabaseDemoFrame::OnAbout
)
581 EVT_CLOSE(DatabaseDemoFrame::OnCloseWindow
)
585 // DatabaseDemoFrame constructor
586 DatabaseDemoFrame::DatabaseDemoFrame(wxFrame
*frame
, const wxString
& title
,
587 const wxPoint
& pos
, const wxSize
& size
):
588 wxFrame(frame
, -1, title
, pos
, size
)
590 // Put any code in necessary for initializing the main frame here
594 delete wxLog::SetActiveTarget(new wxLogStderr
);
596 } // DatabaseDemoFrame constructor
598 DatabaseDemoFrame::~DatabaseDemoFrame()
600 delete wxLog::SetActiveTarget(NULL
);
601 } // DatabaseDemoFrame destructor
604 void DatabaseDemoFrame::OnCreate(wxCommandEvent
& event
)
606 wxGetApp().CreateDataTable(FALSE
);
607 } // DatabaseDemoFrame::OnCreate()
610 void DatabaseDemoFrame::OnRecreateTable(wxCommandEvent
& event
)
612 wxGetApp().CreateDataTable(TRUE
);
613 } // DatabaseDemoFrame::OnRecreate()
616 void DatabaseDemoFrame::OnRecreateIndexes(wxCommandEvent
& event
)
618 if (!wxGetApp().Contact
->CreateIndexes())
623 tStr
= wxT("Error creating CONTACTS indexes.\nNew indexes will be unavailable.\n\n");
624 tStr
+= GetExtendedDBErrorMsg(wxGetApp().Contact
->GetDb(),__FILE__
,__LINE__
);
625 wxMessageBox(tStr
,wxT("ODBC Error..."),wxOK
| wxICON_EXCLAMATION
);
628 wxMessageBox(wxT("Index(es) were successfully recreated."),wxT("Notice..."),wxOK
| wxICON_INFORMATION
);
630 } // DatabaseDemoFrame::OnRecreateIndexes()
633 void DatabaseDemoFrame::OnExit(wxCommandEvent
& event
)
636 } // DatabaseDemoFrame::OnExit()
639 void DatabaseDemoFrame::OnEditParameters(wxCommandEvent
& event
)
641 if ((pEditorDlg
->mode
!= mCreate
) && (pEditorDlg
->mode
!= mEdit
))
642 BuildParameterDialog(this);
644 wxMessageBox(wxT("Cannot change database parameters while creating or editing a record"),wxT("Notice..."),wxOK
| wxICON_INFORMATION
);
645 } // DatabaseDemoFrame::OnEditParameters()
648 void DatabaseDemoFrame::OnAbout(wxCommandEvent
& event
)
650 wxMessageBox(wxT("wxWindows sample program for database classes\n\nContributed on 27 July 1998"),wxT("About..."),wxOK
| wxICON_INFORMATION
);
651 } // DatabaseDemoFrame::OnAbout()
654 // Put any additional checking necessary to make certain it is alright
655 // to close the program here that is not done elsewhere
656 void DatabaseDemoFrame::OnCloseWindow(wxCloseEvent
& event
)
659 if (pEditorDlg
&& pEditorDlg
->Close())
670 wxDELETE(wxGetApp().Contact
);
672 // This function will close all the connections to the database that have been
673 // previously cached.
674 wxDbCloseConnections();
676 // Deletion of the wxDbConnectInf instance must be the LAST thing done that
677 // has anything to do with the database. Deleting this before disconnecting,
678 // freeing/closing connections, etc will result in a crash!
679 wxDELETE(wxGetApp().DbConnectInf
);
683 } // DatabaseDemoFrame::OnCloseWindow()
686 void DatabaseDemoFrame::BuildEditorDialog()
689 pEditorDlg
= new CeditorDlg(this);
692 pEditorDlg
->Initialize();
693 if (!pEditorDlg
->initialized
)
697 wxMessageBox(wxT("Unable to initialize the editor dialog for some reason"),wxT("Error..."),wxOK
| wxICON_EXCLAMATION
);
703 wxMessageBox(wxT("Unable to create the editor dialog for some reason"),wxT("Error..."),wxOK
| wxICON_EXCLAMATION
);
706 } // DatabaseDemoFrame::BuildEditorDialog()
709 void DatabaseDemoFrame::BuildParameterDialog(wxWindow
*parent
)
711 pParamDlg
= new CparameterDlg(parent
);
714 wxMessageBox(wxT("Unable to create the parameter dialog for some reason"),wxT("Error..."),wxOK
| wxICON_EXCLAMATION
);
715 } // DatabaseDemoFrame::BuildParameterDialog()
719 * Constructor note: If no wxDb object is passed in, a new connection to the database
720 * is created for this instance of Ccontact. This can be a slow process depending
721 * on the database engine being used, and some database engines have a limit on the
722 * number of connections (either hard limits, or license restricted) so care should
723 * be used to use as few connections as is necessary.
725 * IMPORTANT: Objects which share a wxDb pointer are ALL acted upon whenever a member
726 * function of pDb is called (i.e. CommitTrans() or RollbackTrans(), so if modifying
727 * or creating a table objects which use the same pDb, know that all the objects
728 * will be committed or rolled back when any of the objects has this function call made.
730 Ccontact::Ccontact (wxDb
*pwxDb
) : wxDbTable(pwxDb
? pwxDb
: wxDbGetConnection(wxGetApp().DbConnectInf
),
731 CONTACT_TABLE_NAME
, CONTACT_NO_COLS
, wxT(""),
732 !wxDB_QUERY_ONLY
, wxGetApp().DbConnectInf
->GetDefaultDir())
734 // This is used to represent whether the database connection should be released
735 // when this instance of the object is deleted. If using the same connection
736 // for multiple instance of database objects, then the connection should only be
737 // released when the last database instance using the connection is deleted
741 GetDb()->SetSqlLogging(sqlLogON
);
745 } // Ccontact Constructor
748 void Ccontact::Initialize()
757 JoinDate
.year
= 1980;
763 JoinDate
.fraction
= 0;
764 NativeLanguage
= langENGLISH
;
768 } // Ccontact::Initialize
771 Ccontact::~Ccontact()
775 if (!wxDbFreeConnection(GetDb()))
778 tStr
= wxT("Unable to Free the Ccontact data table handle\n\n");
779 tStr
+= GetExtendedDBErrorMsg(GetDb(),__FILE__
,__LINE__
);
780 wxMessageBox(tStr
,wxT("ODBC Error..."),wxOK
| wxICON_EXCLAMATION
);
783 } // Ccontract destructor
787 * Handles setting up all the connections for the interface from the wxDbTable
788 * functions to interface to the data structure used to store records in
789 * memory, and for all the column definitions that define the table structure
791 void Ccontact::SetupColumns()
793 // NOTE: Columns now are 8 character names, as that is all dBase can support. Longer
794 // names can be used for other database engines
795 SetColDefs ( 0,wxT("NAME"), DB_DATA_TYPE_VARCHAR
, Name
, SQL_C_CHAR
, sizeof(Name
), TRUE
, TRUE
); // Primary index
796 SetColDefs ( 1,wxT("ADDRESS1"), DB_DATA_TYPE_VARCHAR
, Addr1
, SQL_C_CHAR
, sizeof(Addr1
), FALSE
,TRUE
);
797 SetColDefs ( 2,wxT("ADDRESS2"), DB_DATA_TYPE_VARCHAR
, Addr2
, SQL_C_CHAR
, sizeof(Addr2
), FALSE
,TRUE
);
798 SetColDefs ( 3,wxT("CITY"), DB_DATA_TYPE_VARCHAR
, City
, SQL_C_CHAR
, sizeof(City
), FALSE
,TRUE
);
799 SetColDefs ( 4,wxT("STATE"), DB_DATA_TYPE_VARCHAR
, State
, SQL_C_CHAR
, sizeof(State
), FALSE
,TRUE
);
800 SetColDefs ( 5,wxT("POSTCODE"), DB_DATA_TYPE_VARCHAR
, PostalCode
, SQL_C_CHAR
, sizeof(PostalCode
), FALSE
,TRUE
);
801 SetColDefs ( 6,wxT("COUNTRY"), DB_DATA_TYPE_VARCHAR
, Country
, SQL_C_CHAR
, sizeof(Country
), FALSE
,TRUE
);
802 SetColDefs ( 7,wxT("JOINDATE"), DB_DATA_TYPE_DATE
, &JoinDate
, SQL_C_TIMESTAMP
, sizeof(JoinDate
), FALSE
,TRUE
);
803 SetColDefs ( 8,wxT("IS_DEV"), DB_DATA_TYPE_INTEGER
, &IsDeveloper
, SQL_C_BOOLEAN(IsDeveloper
), sizeof(IsDeveloper
), FALSE
,TRUE
);
804 SetColDefs ( 9,wxT("CONTRIBS"), DB_DATA_TYPE_INTEGER
, &Contributions
, SQL_C_USHORT
, sizeof(Contributions
), FALSE
,TRUE
);
805 SetColDefs (10,wxT("LINE_CNT"), DB_DATA_TYPE_INTEGER
, &LinesOfCode
, SQL_C_ULONG
, sizeof(LinesOfCode
), FALSE
,TRUE
);
806 SetColDefs (11,wxT("LANGUAGE"), DB_DATA_TYPE_INTEGER
, &NativeLanguage
, SQL_C_ENUM
, sizeof(NativeLanguage
), FALSE
,TRUE
);
807 #if wxODBC_BLOB_EXPERIMENT > 0
808 SetColDefs (12,wxT("PICTURE"), DB_DATA_TYPE_BLOB
, Picture
, SQL_LONGVARBINARY
, sizeof(Picture
), FALSE
,TRUE
);
810 } // Ccontact::SetupColumns
813 bool Ccontact::CreateIndexes(void)
815 // This index could easily be accomplished with an "orderBy" clause,
816 // but is done to show how to construct a non-primary index.
818 wxDbIdxDef idxDef
[2];
822 wxStrcpy(idxDef
[0].ColName
, "IS_DEV");
823 idxDef
[0].Ascending
= TRUE
;
825 wxStrcpy(idxDef
[1].ColName
, "NAME");
826 idxDef
[1].Ascending
= TRUE
;
828 indexName
= GetTableName();
829 indexName
+= "_IDX1";
830 Ok
= CreateIndex(indexName
.c_str(), TRUE
, 2, idxDef
);
833 } // Ccontact::CreateIndexes()
837 * Having a function to do a query on the primary key (and possibly others) is
838 * very efficient and tighter coding so that it is available where ever the object
839 * is. Great for use with multiple tables when not using views or outer joins
841 bool Ccontact::FetchByName(const wxString
&name
)
843 whereStr
.Printf(wxT("NAME = '%s'"),name
.c_str());
844 SetWhereClause(whereStr
.c_str());
845 SetOrderByClause(wxT(""));
853 } // Ccontact::FetchByName()
858 * ************* DIALOGS ***************
863 /* CeditorDlg constructor
865 * Creates the dialog used for creating/editing/deleting/copying a Ccontact object.
866 * This dialog actually is drawn in the main frame of the program
868 * An instance of Ccontact is created - "Contact" - which is used to hold the Ccontact
869 * object that is currently being worked with.
872 BEGIN_EVENT_TABLE(CeditorDlg
, wxPanel
)
873 EVT_BUTTON(-1, CeditorDlg::OnButton
)
874 EVT_CLOSE(CeditorDlg::OnCloseWindow
)
877 CeditorDlg::CeditorDlg(wxWindow
*parent
) : wxPanel (parent
, 0, 0, 537, 480)
879 // Since the ::OnCommand() function is overridden, this prevents the widget
880 // detection in ::OnCommand() until all widgets have been initialized to prevent
881 // uninitialized pointers from crashing the program
882 widgetPtrsSet
= FALSE
;
889 } // CeditorDlg constructor
892 void CeditorDlg::OnCloseWindow(wxCloseEvent
& event
)
895 if ((mode
!= mCreate
) && (mode
!= mEdit
))
901 wxMessageBox(wxT("Must finish processing the current record being created/modified before exiting"),wxT("Notice..."),wxOK
| wxICON_INFORMATION
);
904 } // CeditorDlg::OnCloseWindow()
907 void CeditorDlg::OnButton(wxCommandEvent
&event
)
909 wxWindow
*win
= (wxWindow
*) event
.GetEventObject();
910 OnCommand( *win
, event
);
911 } // CeditorDlg::OnButton()
914 void CeditorDlg::OnCommand(wxWindow
& win
, wxCommandEvent
& event
)
918 widgetName
= win
.GetName();
923 if (widgetName
== pCreateBtn
->GetName())
925 wxGetApp().Contact
->Initialize();
928 pNameTxt
->SetValue(wxT(""));
929 pNameTxt
->SetFocus();
933 if (widgetName
== pEditBtn
->GetName())
935 saveName
= wxGetApp().Contact
->Name
;
937 pNameTxt
->SetFocus();
941 if (widgetName
== pCopyBtn
->GetName())
944 pNameTxt
->SetValue(wxT(""));
945 pNameTxt
->SetFocus();
949 if (widgetName
== pDeleteBtn
->GetName())
951 bool Ok
= (wxMessageBox(wxT("Are you sure?"),wxT("Confirm"),wxYES_NO
|wxICON_QUESTION
) == wxYES
);
956 if (Ok
&& wxGetApp().Contact
->Delete())
958 // NOTE: Deletions are not finalized until a CommitTrans() is performed.
959 // If the commit were not performed, the program will continue to
960 // show the table contents as if they were deleted until this instance
961 // of Ccontact is deleted. If the Commit wasn't performed, the
962 // database will automatically Rollback the changes when the database
963 // connection is terminated
964 wxGetApp().Contact
->GetDb()->CommitTrans();
966 // Try to get the row that followed the just deleted row in the orderBy sequence
969 // There was now row (in sequence) after the just deleted row, so get the
970 // row which preceded the just deleted row
973 // There are now no rows remaining, so clear the dialog widgets
974 wxGetApp().Contact
->Initialize();
978 SetMode(mode
); // force reset of button enable/disable
982 wxGetApp().Contact
->GetDb()->RollbackTrans();
988 if (widgetName
== pSaveBtn
->GetName())
994 if (widgetName
== pCancelBtn
->GetName())
996 bool Ok
= (wxMessageBox(wxT("Are you sure?"),wxT("Confirm"),wxYES_NO
|wxICON_QUESTION
) == wxYES
);
1001 if (saveName
.IsEmpty())
1003 wxGetApp().Contact
->Initialize();
1010 // Requery previous record
1011 if (wxGetApp().Contact
->FetchByName(saveName
))
1019 // Previous record not available, retrieve first record in table
1020 if (wxGetApp().Contact
->GetDb()->Dbms() != dbmsPOSTGRES
&&
1021 wxGetApp().Contact
->GetDb()->Dbms() != dbmsMY_SQL
)
1023 wxGetApp().Contact
->whereStr
= wxT("NAME = (SELECT MIN(NAME) FROM ");
1024 wxGetApp().Contact
->whereStr
+= wxGetApp().Contact
->GetTableName();
1025 wxGetApp().Contact
->whereStr
+= wxT(")");
1026 wxGetApp().Contact
->SetWhereClause(wxGetApp().Contact
->whereStr
.c_str());
1029 wxGetApp().Contact
->SetWhereClause(wxT(""));
1031 if (!wxGetApp().Contact
->Query())
1034 tStr
= wxT("ODBC error during Query()\n\n");
1035 tStr
+= GetExtendedDBErrorMsg(wxGetApp().Contact
->GetDb(),__FILE__
,__LINE__
);
1036 wxMessageBox(tStr
,wxT("ODBC Error..."),wxOK
| wxICON_EXCLAMATION
);
1040 if (wxGetApp().Contact
->GetNext()) // Successfully read first record
1046 // No contacts are available, clear dialog
1047 wxGetApp().Contact
->Initialize();
1053 if (widgetName
== pPrevBtn
->GetName())
1060 if (widgetName
== pNextBtn
->GetName())
1067 if (widgetName
== pQueryBtn
->GetName())
1069 // Display the query dialog box
1070 wxChar qryWhere
[DB_MAX_WHERE_CLAUSE_LEN
+1];
1071 wxStrcpy(qryWhere
, (const wxChar
*) wxGetApp().Contact
->qryWhereStr
);
1072 wxChar
*tblName
[] = {(wxChar
*)CONTACT_TABLE_NAME
, 0};
1073 new CqueryDlg(GetParent(), wxGetApp().Contact
->GetDb(), tblName
, qryWhere
);
1075 // Query the first record in the new record set and
1076 // display it, if the query string has changed.
1077 if (wxStrcmp(qryWhere
, (const wxChar
*) wxGetApp().Contact
->qryWhereStr
))
1079 wxGetApp().Contact
->whereStr
.Empty();
1080 wxGetApp().Contact
->SetOrderByClause("NAME");
1082 if (wxGetApp().Contact
->GetDb()->Dbms() != dbmsPOSTGRES
&&
1083 wxGetApp().Contact
->GetDb()->Dbms() != dbmsMY_SQL
)
1085 wxGetApp().Contact
->whereStr
= wxT("NAME = (SELECT MIN(NAME) FROM ");
1086 wxGetApp().Contact
->whereStr
+= CONTACT_TABLE_NAME
;
1089 // Append the query where string (if there is one)
1090 wxGetApp().Contact
->qryWhereStr
= qryWhere
;
1091 if (wxStrlen(qryWhere
))
1093 wxGetApp().Contact
->whereStr
+= wxT(" WHERE ");
1094 wxGetApp().Contact
->whereStr
+= wxGetApp().Contact
->qryWhereStr
;
1096 // Close the expression with a right paren
1097 wxGetApp().Contact
->whereStr
+= wxT(")");
1098 // Requery the table
1099 wxGetApp().Contact
->SetWhereClause(wxGetApp().Contact
->whereStr
.c_str());
1100 if (!wxGetApp().Contact
->Query())
1103 tStr
= wxT("ODBC error during Query()\n\n");
1104 tStr
+= GetExtendedDBErrorMsg(wxGetApp().Contact
->GetDb(),__FILE__
,__LINE__
);
1105 wxMessageBox(tStr
,wxT("ODBC Error..."),wxOK
| wxICON_EXCLAMATION
);
1108 // Display the first record from the query set
1109 if (!wxGetApp().Contact
->GetNext())
1110 wxGetApp().Contact
->Initialize();
1114 // Enable/Disable the reset button
1115 pResetBtn
->Enable(!wxGetApp().Contact
->qryWhereStr
.IsEmpty());
1121 if (widgetName
== pResetBtn
->GetName())
1123 // Clear the additional where criteria established by the query feature
1124 wxGetApp().Contact
->qryWhereStr
= wxT("");
1125 wxGetApp().Contact
->SetOrderByClause(wxT("NAME"));
1127 if (wxGetApp().Contact
->GetDb()->Dbms() != dbmsPOSTGRES
&&
1128 wxGetApp().Contact
->GetDb()->Dbms() != dbmsMY_SQL
)
1130 wxGetApp().Contact
->whereStr
= wxT("NAME = (SELECT MIN(NAME) FROM ");
1131 wxGetApp().Contact
->whereStr
+= CONTACT_TABLE_NAME
;
1132 wxGetApp().Contact
->whereStr
+= wxT(")");
1135 wxGetApp().Contact
->SetWhereClause(wxGetApp().Contact
->whereStr
.c_str());
1136 if (!wxGetApp().Contact
->Query())
1139 tStr
= wxT("ODBC error during Query()\n\n");
1140 tStr
+= GetExtendedDBErrorMsg(wxGetApp().Contact
->GetDb(),__FILE__
,__LINE__
);
1141 wxMessageBox(tStr
,wxT("ODBC Error..."),wxOK
| wxICON_EXCLAMATION
);
1144 if (!wxGetApp().Contact
->GetNext())
1145 wxGetApp().Contact
->Initialize();
1147 pResetBtn
->Enable(FALSE
);
1153 if (widgetName
== pNameListBtn
->GetName())
1155 new ClookUpDlg(/* wxWindow *parent */ this,
1156 /* wxChar *windowTitle */ wxT("Select contact name"),
1157 /* wxChar *tableName */ (wxChar
*) CONTACT_TABLE_NAME
,
1158 /* wxChar *dispCol1 */ wxT("NAME"),
1159 /* wxChar *dispCol2 */ wxT("JOINDATE"),
1160 /* wxChar *where */ wxT(""),
1161 /* wxChar *orderBy */ wxT("NAME"),
1162 /* wxDb *pDb */ wxGetApp().READONLY_DB
,
1163 /* const wxString &defDir */ wxGetApp().DbConnectInf
->GetDefaultDir(),
1164 /* bool distinctValues */ TRUE
);
1166 if (ListDB_Selection
&& wxStrlen(ListDB_Selection
))
1168 wxString w
= wxT("NAME = '");
1169 w
+= ListDB_Selection
;
1177 if (widgetName
== pDataTypesBtn
->GetName())
1179 CheckSupportForAllDataTypes(wxGetApp().READONLY_DB
);
1182 } // Data types Button
1184 if (widgetName
== pDbDiagsBtn
->GetName())
1187 strcpy(wxGetApp().Contact->Addr1,"12345678901234567890");
1188 //wxString sqlStmt = "UPDATE CONTACTS set ADDRESS1='1234567890ABCEFG' where NAME='12345'";
1189 //if (wxGetApp().Contact->GetDb()->ExecSql(sqlStmt))
1190 if (wxGetApp().Contact->UpdateWhere("NAME = '12345'"))
1191 wxGetApp().Contact->GetDb()->CommitTrans();
1193 wxGetApp().Contact->GetDb()->RollbackTrans();
1195 DisplayDbDiagnostics(wxGetApp().READONLY_DB
);
1199 } // CeditorDlg::OnCommand()
1202 bool CeditorDlg::Initialize()
1204 // Create the data structure and a new database connection.
1205 // (As there is not a pDb being passed in the constructor, a new database
1206 // connection is created)
1207 wxGetApp().Contact
= new Ccontact();
1209 if (!wxGetApp().Contact
)
1211 wxMessageBox(wxT("Unable to instantiate an instance of Ccontact"),wxT("Error..."),wxOK
| wxICON_EXCLAMATION
);
1215 // Check if the table exists or not. If it doesn't, ask the user if they want to
1216 // create the table. Continue trying to create the table until it exists, or user aborts
1217 while (!wxGetApp().Contact
->GetDb()->TableExists((wxChar
*)CONTACT_TABLE_NAME
,
1218 wxGetApp().DbConnectInf
->GetUserID(),
1219 wxGetApp().DbConnectInf
->GetDefaultDir()))
1222 tStr
.Printf(wxT("Unable to open the table '%s'.\n\nTable may need to be created...?\n\n"),CONTACT_TABLE_NAME
);
1223 tStr
+= GetExtendedDBErrorMsg(wxGetApp().Contact
->GetDb(),__FILE__
,__LINE__
);
1224 wxMessageBox(tStr
,wxT("ODBC Error..."),wxOK
| wxICON_EXCLAMATION
);
1226 bool createTable
= (wxMessageBox(wxT("Do you wish to try to create/clear the CONTACTS table?"),wxT("Confirm"),wxYES_NO
|wxICON_QUESTION
) == wxYES
);
1234 wxGetApp().CreateDataTable(FALSE
);
1237 // Tables must be "opened" before anything other than creating/deleting table can be done
1238 if (!wxGetApp().Contact
->Open())
1240 // Table does exist, or there was some problem opening it. Currently this should
1241 // never fail, except in the case of the table not exisiting or the current
1242 // user has insufficent privileges to access the table
1244 // This code is experimenting with a new function that will hopefully be available
1245 // in the 2.4 release. This check will determine whether the open failing was due
1246 // to the table not existing, or the users privileges being insufficient to
1248 if (!wxGetApp().Contact
->GetDb()->TablePrivileges(CONTACT_TABLE_NAME
, wxT("SELECT"),
1249 wxGetApp().Contact
->GetDb()->GetUsername(),
1250 wxGetApp().Contact
->GetDb()->GetUsername(),
1251 wxGetApp().DbConnectInf
->GetDefaultDir()))
1254 tStr
.Printf(wxT("Unable to open the table '%s' (likely due to\ninsufficient privileges of the logged in user).\n\n"),CONTACT_TABLE_NAME
);
1255 tStr
+= GetExtendedDBErrorMsg(wxGetApp().Contact
->GetDb(),__FILE__
,__LINE__
);
1256 wxMessageBox(tStr
,wxT("ODBC Error..."),wxOK
| wxICON_EXCLAMATION
);
1260 if (!wxGetApp().Contact
->GetDb()->TableExists(CONTACT_TABLE_NAME
,
1261 wxGetApp().Contact
->GetDb()->GetUsername(),
1262 wxGetApp().DbConnectInf
->GetDefaultDir()))
1265 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
);
1266 tStr
+= GetExtendedDBErrorMsg(wxGetApp().Contact
->GetDb(),__FILE__
,__LINE__
);
1267 wxMessageBox(tStr
,wxT("ODBC Error..."),wxOK
| wxICON_EXCLAMATION
);
1275 (void)new wxStaticBox(this, EDITOR_DIALOG_FN_GROUP
, wxT(""), wxPoint(15, 1), wxSize(497, 69), 0, wxT("FunctionGrp"));
1276 (void)new wxStaticBox(this, EDITOR_DIALOG_SEARCH_GROUP
, wxT(""), wxPoint(417, 1), wxSize(95, 242), 0, wxT("SearchGrp"));
1278 pCreateBtn
= new wxButton(this, EDITOR_DIALOG_CREATE
, wxT("&Create"), wxPoint( 25, 21), wxSize( 70, 35), 0, wxDefaultValidator
, wxT("CreateBtn"));
1279 pEditBtn
= new wxButton(this, EDITOR_DIALOG_EDIT
, wxT("&Edit"), wxPoint(102, 21), wxSize( 70, 35), 0, wxDefaultValidator
, wxT("EditBtn"));
1280 pDeleteBtn
= new wxButton(this, EDITOR_DIALOG_DELETE
, wxT("&Delete"), wxPoint(179, 21), wxSize( 70, 35), 0, wxDefaultValidator
, wxT("DeleteBtn"));
1281 pCopyBtn
= new wxButton(this, EDITOR_DIALOG_COPY
, wxT("Cop&y"), wxPoint(256, 21), wxSize( 70, 35), 0, wxDefaultValidator
, wxT("CopyBtn"));
1282 pSaveBtn
= new wxButton(this, EDITOR_DIALOG_SAVE
, wxT("&Save"), wxPoint(333, 21), wxSize( 70, 35), 0, wxDefaultValidator
, wxT("SaveBtn"));
1283 pCancelBtn
= new wxButton(this, EDITOR_DIALOG_CANCEL
, wxT("C&ancel"), wxPoint(430, 21), wxSize( 70, 35), 0, wxDefaultValidator
, wxT("CancelBtn"));
1284 pPrevBtn
= new wxButton(this, EDITOR_DIALOG_PREV
, wxT("<< &Prev"), wxPoint(430, 81), wxSize( 70, 35), 0, wxDefaultValidator
, wxT("PrevBtn"));
1285 pNextBtn
= new wxButton(this, EDITOR_DIALOG_NEXT
, wxT("&Next >>"), wxPoint(430, 121), wxSize( 70, 35), 0, wxDefaultValidator
, wxT("NextBtn"));
1286 pQueryBtn
= new wxButton(this, EDITOR_DIALOG_QUERY
, wxT("&Query"), wxPoint(430, 161), wxSize( 70, 35), 0, wxDefaultValidator
, wxT("QueryBtn"));
1287 pResetBtn
= new wxButton(this, EDITOR_DIALOG_RESET
, wxT("&Reset"), wxPoint(430, 200), wxSize( 70, 35), 0, wxDefaultValidator
, wxT("ResetBtn"));
1288 pNameMsg
= new wxStaticText(this, EDITOR_DIALOG_NAME_MSG
, wxT("Name:"), wxPoint( 17, 80), wxSize( -1, -1), 0, wxT("NameMsg"));
1289 pNameTxt
= new wxTextCtrl(this, EDITOR_DIALOG_NAME_TEXT
, wxT(""), wxPoint( 17, 97), wxSize(308, 25), 0, wxDefaultValidator
, wxT("NameTxt"));
1290 pNameListBtn
= new wxButton(this, EDITOR_DIALOG_LOOKUP
, wxT("&Lookup"), wxPoint(333, 97), wxSize( 70, 24), 0, wxDefaultValidator
, wxT("LookupBtn"));
1291 pAddress1Msg
= new wxStaticText(this, EDITOR_DIALOG_ADDRESS1_MSG
, wxT("Address:"), wxPoint( 17, 130), wxSize( -1, -1), 0, wxT("Address1Msg"));
1292 pAddress1Txt
= new wxTextCtrl(this, EDITOR_DIALOG_ADDRESS2_TEXT
, wxT(""), wxPoint( 17, 147), wxSize(308, 25), 0, wxDefaultValidator
, wxT("Address1Txt"));
1293 pAddress2Msg
= new wxStaticText(this, EDITOR_DIALOG_ADDRESS2_MSG
, wxT("Address:"), wxPoint( 17, 180), wxSize( -1, -1), 0, wxT("Address2Msg"));
1294 pAddress2Txt
= new wxTextCtrl(this, EDITOR_DIALOG_ADDRESS2_TEXT
, wxT(""), wxPoint( 17, 197), wxSize(308, 25), 0, wxDefaultValidator
, wxT("Address2Txt"));
1295 pCityMsg
= new wxStaticText(this, EDITOR_DIALOG_CITY_MSG
, wxT("City:"), wxPoint( 17, 230), wxSize( -1, -1), 0, wxT("CityMsg"));
1296 pCityTxt
= new wxTextCtrl(this, EDITOR_DIALOG_CITY_TEXT
, wxT(""), wxPoint( 17, 247), wxSize(225, 25), 0, wxDefaultValidator
, wxT("CityTxt"));
1297 pStateMsg
= new wxStaticText(this, EDITOR_DIALOG_STATE_MSG
, wxT("State:"), wxPoint(250, 230), wxSize( -1, -1), 0, wxT("StateMsg"));
1298 pStateTxt
= new wxTextCtrl(this, EDITOR_DIALOG_STATE_TEXT
, wxT(""), wxPoint(250, 247), wxSize(153, 25), 0, wxDefaultValidator
, wxT("StateTxt"));
1299 pCountryMsg
= new wxStaticText(this, EDITOR_DIALOG_COUNTRY_MSG
, wxT("Country:"), wxPoint( 17, 280), wxSize( -1, -1), 0, wxT("CountryMsg"));
1300 pCountryTxt
= new wxTextCtrl(this, EDITOR_DIALOG_COUNTRY_TEXT
, wxT(""), wxPoint( 17, 297), wxSize(225, 25), 0, wxDefaultValidator
, wxT("CountryTxt"));
1301 pPostalCodeMsg
= new wxStaticText(this, EDITOR_DIALOG_POSTAL_MSG
, wxT("Postal Code:"),wxPoint(250, 280), wxSize( -1, -1), 0, wxT("PostalCodeMsg"));
1302 pPostalCodeTxt
= new wxTextCtrl(this, EDITOR_DIALOG_POSTAL_TEXT
, wxT(""), wxPoint(250, 297), wxSize(153, 25), 0, wxDefaultValidator
, wxT("PostalCodeTxt"));
1304 wxString choice_strings
[5];
1305 choice_strings
[0] = wxT("English");
1306 choice_strings
[1] = wxT("French");
1307 choice_strings
[2] = wxT("German");
1308 choice_strings
[3] = wxT("Spanish");
1309 choice_strings
[4] = wxT("Other");
1311 pNativeLangChoice
= new wxChoice(this, EDITOR_DIALOG_LANG_CHOICE
, wxPoint( 17, 346), wxSize(277, -1), 5, choice_strings
);
1312 pNativeLangMsg
= new wxStaticText(this, EDITOR_DIALOG_LANG_MSG
, wxT("Native language:"), wxPoint( 17, 330), wxSize( -1, -1), 0, wxT("NativeLangMsg"));
1314 wxString radio_strings
[2];
1315 radio_strings
[0] = wxT("No");
1316 radio_strings
[1] = wxT("Yes");
1317 pDeveloperRadio
= new wxRadioBox(this,EDITOR_DIALOG_DEVELOPER
, wxT("Developer:"), wxPoint(303, 330), wxSize( -1, -1), 2, radio_strings
, 2, wxHORIZONTAL
);
1318 pJoinDateMsg
= new wxStaticText(this, EDITOR_DIALOG_JOIN_MSG
, wxT("Date joined:"), wxPoint( 17, 380), wxSize( -1, -1), 0, wxT("JoinDateMsg"));
1319 pJoinDateTxt
= new wxTextCtrl(this, EDITOR_DIALOG_JOIN_TEXT
, wxT(""), wxPoint( 17, 397), wxSize(150, 25), 0, wxDefaultValidator
, wxT("JoinDateTxt"));
1320 pContribMsg
= new wxStaticText(this, EDITOR_DIALOG_CONTRIB_MSG
,wxT("Contributions:"), wxPoint(175, 380), wxSize( -1, -1), 0, wxT("ContribMsg"));
1321 pContribTxt
= new wxTextCtrl(this, EDITOR_DIALOG_CONTRIB_TEXT
, wxT(""), wxPoint(175, 397), wxSize(120, 25), 0, wxDefaultValidator
, wxT("ContribTxt"));
1322 pLinesMsg
= new wxStaticText(this, EDITOR_DIALOG_LINES_MSG
, wxT("Lines of code:"), wxPoint(303, 380), wxSize( -1, -1), 0, wxT("LinesMsg"));
1323 pLinesTxt
= new wxTextCtrl(this, EDITOR_DIALOG_LINES_TEXT
, wxT(""), wxPoint(303, 397), wxSize(100, 25), 0, wxDefaultValidator
, wxT("LinesTxt"));
1325 pDataTypesBtn
= new wxButton(this, EDITOR_DIALOG_DATATYPES
, wxT("Data&types"), wxPoint(430, 337), wxSize( 70, 35), 0, wxDefaultValidator
, wxT("DataTypesBtn"));
1326 pDbDiagsBtn
= new wxButton(this, EDITOR_DIALOG_DB_DIAGS
, wxT("DB Dia&gs"), wxPoint(430, 387), wxSize( 70, 35), 0, wxDefaultValidator
, wxT("DbDiagsBtn"));
1328 // Now that all the widgets on the panel are created, its safe to allow ::OnCommand() to
1329 // handle all widget processing
1330 widgetPtrsSet
= TRUE
;
1332 // Setup the orderBy and where clauses to return back a single record as the result set,
1333 // as there will only be one record being shown on the dialog at a time, this optimizes
1334 // network traffic by only returning a one row result
1336 wxGetApp().Contact
->SetOrderByClause(wxT("NAME")); // field name to sort by
1338 // The wxString "whereStr" is not a member of the wxDbTable object, it is a member variable
1339 // specifically in the Ccontact class. It is used here for simpler construction of a varying
1340 // length string, and then after the string is built, the wxDbTable member variable "where" is
1341 // assigned the pointer to the constructed string.
1343 // The constructed where clause below has a sub-query within it "SELECT MIN(NAME) FROM %s"
1344 // to achieve a single row (in this case the first name in alphabetical order).
1346 if (wxGetApp().Contact
->GetDb()->Dbms() != dbmsPOSTGRES
&&
1347 wxGetApp().Contact
->GetDb()->Dbms() != dbmsMY_SQL
)
1349 wxGetApp().Contact
->whereStr
.Printf(wxT("NAME = (SELECT MIN(NAME) FROM %s)"),
1350 wxGetApp().Contact
->GetTableName().c_str());
1351 // NOTE: (const wxChar*) returns a pointer which may not be valid later, so this is short term use only
1352 wxGetApp().Contact
->SetWhereClause(wxGetApp().Contact
->whereStr
);
1355 wxGetApp().Contact
->SetWhereClause(wxT(""));
1357 // Perform the Query to get the result set.
1358 // NOTE: If there are no rows returned, that is a valid result, so Query() would return TRUE.
1359 // Only if there is a database error will Query() come back as FALSE
1360 if (!wxGetApp().Contact
->Query())
1363 tStr
= wxT("ODBC error during Query()\n\n");
1364 tStr
+= GetExtendedDBErrorMsg(wxGetApp().Contact
->GetDb(),__FILE__
,__LINE__
);
1365 wxMessageBox(tStr
,wxT("ODBC Error..."),wxOK
| wxICON_EXCLAMATION
);
1369 // Since Query succeeded, now get the row that was returned
1370 if (!wxGetApp().Contact
->GetNext())
1371 // If the GetNext() failed at this point, then there are no rows to retrieve,
1372 // so clear the values in the members of "Contact" so that PutData() blanks the
1373 // widgets on the dialog
1374 wxGetApp().Contact
->Initialize();
1376 wxGetApp().Contact->GetDb()->RollbackTrans();
1385 } // CeditorDlg::Initialize()
1388 void CeditorDlg::FieldsEditable()
1393 pNameTxt
->Enable((mode
== mCreate
) || (mode
== mEdit
));
1394 pAddress1Txt
->Enable((mode
== mCreate
) || (mode
== mEdit
));
1395 pAddress2Txt
->Enable((mode
== mCreate
) || (mode
== mEdit
));
1396 pCityTxt
->Enable((mode
== mCreate
) || (mode
== mEdit
));
1397 pStateTxt
->Enable((mode
== mCreate
) || (mode
== mEdit
));
1398 pPostalCodeTxt
->Enable((mode
== mCreate
) || (mode
== mEdit
));
1399 pCountryTxt
->Enable((mode
== mCreate
) || (mode
== mEdit
));
1401 pJoinDateTxt
->Enable((mode
== mCreate
) || (mode
== mEdit
));
1402 pContribTxt
->Enable((mode
== mCreate
) || (mode
== mEdit
));
1403 pLinesTxt
->Enable((mode
== mCreate
) || (mode
== mEdit
));
1404 pNativeLangChoice
->Enable((mode
== mCreate
) || (mode
== mEdit
));
1405 pDeveloperRadio
->Enable((mode
== mCreate
) || (mode
== mEdit
));
1407 } // CeditorDlg::FieldsEditable()
1410 void CeditorDlg::SetMode(enum DialogModes m
)
1431 pCreateBtn
->Enable( !edit
);
1432 pEditBtn
->Enable( !edit
&& (wxStrcmp(wxGetApp().Contact
->Name
,wxT(""))!=0) );
1433 pDeleteBtn
->Enable( !edit
&& (wxStrcmp(wxGetApp().Contact
->Name
,wxT(""))!=0) );
1434 pCopyBtn
->Enable( !edit
&& (wxStrcmp(wxGetApp().Contact
->Name
,wxT(""))!=0) );
1435 pSaveBtn
->Enable( edit
);
1436 pCancelBtn
->Enable( edit
);
1437 pPrevBtn
->Enable( !edit
);
1438 pNextBtn
->Enable( !edit
);
1439 pQueryBtn
->Enable( !edit
);
1440 pResetBtn
->Enable( !edit
&& !wxGetApp().Contact
->qryWhereStr
.IsEmpty() );
1441 pNameListBtn
->Enable( !edit
);
1445 } // CeditorDlg::SetMode()
1448 bool CeditorDlg::PutData()
1452 pNameTxt
->SetValue(wxGetApp().Contact
->Name
);
1453 pAddress1Txt
->SetValue(wxGetApp().Contact
->Addr1
);
1454 pAddress2Txt
->SetValue(wxGetApp().Contact
->Addr2
);
1455 pCityTxt
->SetValue(wxGetApp().Contact
->City
);
1456 pStateTxt
->SetValue(wxGetApp().Contact
->State
);
1457 pCountryTxt
->SetValue(wxGetApp().Contact
->Country
);
1458 pPostalCodeTxt
->SetValue(wxGetApp().Contact
->PostalCode
);
1460 tStr
.Printf(wxT("%d/%d/%d"),wxGetApp().Contact
->JoinDate
.month
,wxGetApp().Contact
->JoinDate
.day
,wxGetApp().Contact
->JoinDate
.year
);
1461 pJoinDateTxt
->SetValue(tStr
);
1463 tStr
.Printf(wxT("%d"),wxGetApp().Contact
->Contributions
);
1464 pContribTxt
->SetValue(tStr
);
1466 tStr
.Printf(wxT("%lu"),wxGetApp().Contact
->LinesOfCode
);
1467 pLinesTxt
->SetValue(tStr
);
1469 pNativeLangChoice
->SetSelection(wxGetApp().Contact
->NativeLanguage
);
1471 pDeveloperRadio
->SetSelection(wxGetApp().Contact
->IsDeveloper
);
1474 } // Ceditor::PutData()
1478 * Reads the data out of all the widgets on the dialog. Some data evaluation is done
1479 * to ensure that there is a name entered and that the date field is valid.
1481 * A return value of TRUE means that valid data was retrieved from the dialog, otherwise
1482 * invalid data was found (and a message was displayed telling the user what to fix), and
1483 * the data was not placed into the appropraite fields of Ccontact
1485 bool CeditorDlg::GetData()
1487 // Validate that the data currently entered into the widgets is valid data
1490 tStr
= pNameTxt
->GetValue();
1491 if (!wxStrcmp((const wxChar
*) tStr
,wxT("")))
1493 wxMessageBox(wxT("A name is required for entry into the contact table"),wxT("Notice..."),wxOK
| wxICON_INFORMATION
);
1497 bool invalid
= FALSE
;
1501 tStr
= pJoinDateTxt
->GetValue();
1502 if (tStr
.Freq(wxT('/')) != 2)
1505 // Find the month, day, and year tokens
1508 first
= tStr
.First(wxT('/'));
1509 second
= tStr
.Last(wxT('/'));
1511 mm
= atoi(tStr
.SubString(0,first
));
1512 dd
= atoi(tStr
.SubString(first
+1,second
));
1513 yyyy
= atoi(tStr
.SubString(second
+1,tStr
.Length()-1));
1515 invalid
= !(mm
&& dd
&& yyyy
);
1518 // Force Year 2000 compliance
1519 if (!invalid
&& (yyyy
< 1000))
1522 // Check the token ranges for validity
1527 else if ((mm
< 1) || (mm
> 12))
1535 int days
[12] = {31,28,31,30,31,30,
1537 if (dd
> days
[mm
-1])
1540 if ((dd
== 29) && (mm
== 2))
1542 if (((yyyy
% 4) == 0) && (((yyyy
% 100) != 0) || ((yyyy
% 400) == 0)))
1552 wxGetApp().Contact
->JoinDate
.month
= mm
;
1553 wxGetApp().Contact
->JoinDate
.day
= dd
;
1554 wxGetApp().Contact
->JoinDate
.year
= yyyy
;
1558 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
);
1562 tStr
= pNameTxt
->GetValue();
1563 wxStrcpy(wxGetApp().Contact
->Name
,(const wxChar
*) tStr
);
1564 wxStrcpy(wxGetApp().Contact
->Addr1
,pAddress1Txt
->GetValue());
1565 wxStrcpy(wxGetApp().Contact
->Addr2
,pAddress2Txt
->GetValue());
1566 wxStrcpy(wxGetApp().Contact
->City
,pCityTxt
->GetValue());
1567 wxStrcpy(wxGetApp().Contact
->State
,pStateTxt
->GetValue());
1568 wxStrcpy(wxGetApp().Contact
->Country
,pCountryTxt
->GetValue());
1569 wxStrcpy(wxGetApp().Contact
->PostalCode
,pPostalCodeTxt
->GetValue());
1571 wxGetApp().Contact
->Contributions
= atoi(pContribTxt
->GetValue());
1572 wxGetApp().Contact
->LinesOfCode
= atol(pLinesTxt
->GetValue());
1574 wxGetApp().Contact
->NativeLanguage
= (enum Language
) pNativeLangChoice
->GetSelection();
1575 wxGetApp().Contact
->IsDeveloper
= pDeveloperRadio
->GetSelection() > 0;
1578 } // CeditorDlg::GetData()
1582 * Retrieve data from the dialog, verify the validity of the data, and if it is valid,
1583 * try to insert/update the data to the table based on the current 'mode' the dialog
1586 * A return value of TRUE means the insert/update was completed successfully, a return
1587 * value of FALSE means that Save() failed. If returning FALSE, then this function
1588 * has displayed a detailed error message for the user.
1590 bool CeditorDlg::Save()
1592 bool failed
= FALSE
;
1594 // Read the data in the widgets of the dialog to get the user's data
1598 // Perform any other required validations necessary before saving
1601 wxBeginBusyCursor();
1603 if (mode
== mCreate
)
1605 RETCODE result
= wxGetApp().Contact
->Insert();
1607 failed
= (result
!= DB_SUCCESS
);
1610 // Some errors may be expected, like a duplicate key, so handle those instances with
1611 // specific error messages.
1612 if (result
== DB_ERR_INTEGRITY_CONSTRAINT_VIOL
)
1615 tStr
= wxT("A duplicate key value already exists in the table.\nUnable to save record\n\n");
1616 tStr
+= GetExtendedDBErrorMsg(wxGetApp().Contact
->GetDb(),__FILE__
,__LINE__
);
1617 wxMessageBox(tStr
,wxT("ODBC Error..."),wxOK
| wxICON_EXCLAMATION
);
1621 // Some other unexpected error occurred
1623 tStr
= wxT("Database insert failed\n\n");
1624 tStr
+= GetExtendedDBErrorMsg(wxGetApp().Contact
->GetDb(),__FILE__
,__LINE__
);
1625 wxMessageBox(tStr
,wxT("ODBC Error..."),wxOK
| wxICON_EXCLAMATION
);
1629 else // mode == mEdit
1631 wxGetApp().Contact
->GetDb()->RollbackTrans();
1632 wxGetApp().Contact
->whereStr
.Printf("NAME = '%s'",saveName
.c_str());
1633 if (!wxGetApp().Contact
->UpdateWhere(wxGetApp().Contact
->whereStr
))
1636 tStr
= wxT("Database update failed\n\n");
1637 tStr
+= GetExtendedDBErrorMsg(wxGetApp().Contact
->GetDb(),__FILE__
,__LINE__
);
1638 wxMessageBox(tStr
,wxT("ODBC Error..."),wxOK
| wxICON_EXCLAMATION
);
1645 wxGetApp().Contact
->GetDb()->CommitTrans();
1646 SetMode(mView
); // Sets the dialog mode back to viewing after save is successful
1649 wxGetApp().Contact
->GetDb()->RollbackTrans();
1655 } // CeditorDlg::Save()
1659 * Where this program is only showing a single row at a time in the dialog,
1660 * a special where clause must be built to find just the single row which,
1661 * in sequence, would follow the currently displayed row.
1663 bool CeditorDlg::GetNextRec()
1667 if (wxGetApp().Contact
->GetDb()->Dbms() != dbmsPOSTGRES
&&
1668 wxGetApp().Contact
->GetDb()->Dbms() != dbmsMY_SQL
)
1670 w
= wxT("NAME = (SELECT MIN(NAME) FROM ");
1671 w
+= wxGetApp().Contact
->GetTableName();
1672 w
+= wxT(" WHERE NAME > '");
1675 w
= wxT("(NAME > '");
1677 w
+= wxGetApp().Contact
->Name
;
1680 // If a query where string is currently set, append that criteria
1681 if (!wxGetApp().Contact
->qryWhereStr
.IsEmpty())
1684 w
+= wxGetApp().Contact
->qryWhereStr
;
1691 } // CeditorDlg::GetNextRec()
1695 * Where this program is only showing a single row at a time in the dialog,
1696 * a special where clause must be built to find just the single row which,
1697 * in sequence, would precede the currently displayed row.
1699 bool CeditorDlg::GetPrevRec()
1703 if (wxGetApp().Contact
->GetDb()->Dbms() != dbmsPOSTGRES
&&
1704 wxGetApp().Contact
->GetDb()->Dbms() != dbmsMY_SQL
)
1706 w
= wxT("NAME = (SELECT MAX(NAME) FROM ");
1707 w
+= wxGetApp().Contact
->GetTableName();
1708 w
+= wxT(" WHERE NAME < '");
1711 w
= wxT("(NAME < '");
1713 w
+= wxGetApp().Contact
->Name
;
1716 // If a query where string is currently set, append that criteria
1717 if (!wxGetApp().Contact
->qryWhereStr
.IsEmpty())
1720 w
+= wxGetApp().Contact
->qryWhereStr
;
1728 } // CeditorDlg::GetPrevRec()
1732 * This function is here to avoid duplicating this same code in both the
1733 * GetPrevRec() and GetNextRec() functions
1735 bool CeditorDlg::GetRec(const wxString
&whereStr
)
1737 wxGetApp().Contact
->SetWhereClause(whereStr
);
1738 wxGetApp().Contact
->SetOrderByClause(wxT("NAME"));
1740 if (!wxGetApp().Contact
->Query())
1743 tStr
= wxT("ODBC error during Query()\n\n");
1744 tStr
+= GetExtendedDBErrorMsg(wxGetApp().Contact
->GetDb(),__FILE__
,__LINE__
);
1745 wxMessageBox(tStr
,wxT("ODBC Error..."),wxOK
| wxICON_EXCLAMATION
);
1750 if (wxGetApp().Contact
->GetNext())
1757 } // CeditorDlg::GetRec()
1762 * CparameterDlg constructor
1765 BEGIN_EVENT_TABLE(CparameterDlg
, wxDialog
)
1766 EVT_BUTTON(PARAMETER_DIALOG_SAVE
, CparameterDlg::OnButton
)
1767 EVT_BUTTON(PARAMETER_DIALOG_CANCEL
, CparameterDlg::OnButton
)
1768 EVT_CLOSE(CparameterDlg::OnCloseWindow
)
1771 CparameterDlg::CparameterDlg(wxWindow
*parent
) : wxDialog (parent
, PARAMETER_DIALOG
, wxT("ODBC parameter settings"), wxPoint(-1, -1), wxSize(400, 325))
1773 // Since the ::OnCommand() function is overridden, this prevents the widget
1774 // detection in ::OnCommand() until all widgets have been initialized to prevent
1775 // uninitialized pointers from crashing the program
1776 widgetPtrsSet
= FALSE
;
1778 pParamODBCSourceMsg
= new wxStaticText(this, PARAMETER_DIALOG_SOURCE_MSG
, wxT("ODBC data sources:"), wxPoint( 10, 10), wxSize( -1, -1), 0, wxT("ParamODBCSourceMsg"));
1779 pParamODBCSourceList
= new wxListBox(this, PARAMETER_DIALOG_SOURCE_LISTBOX
, wxPoint( 10, 29), wxSize(285, 150), 0, 0, wxLB_SINGLE
|wxLB_ALWAYS_SB
, wxDefaultValidator
, wxT("ParamODBCSourceList"));
1780 pParamUserNameMsg
= new wxStaticText(this, PARAMETER_DIALOG_NAME_MSG
, wxT("Database user name:"), wxPoint( 10, 193), wxSize( -1, -1), 0, wxT("ParamUserNameMsg"));
1781 pParamUserNameTxt
= new wxTextCtrl(this, PARAMETER_DIALOG_NAME_TEXT
, wxT(""), wxPoint(10, 209), wxSize( 140, 25), 0, wxDefaultValidator
, wxT("ParamUserNameTxt"));
1782 pParamPasswordMsg
= new wxStaticText(this, PARAMETER_DIALOG_PASSWORD_MSG
, wxT("Password:"), wxPoint(156, 193), wxSize( -1, -1), 0, wxT("ParamPasswordMsg"));
1783 pParamPasswordTxt
= new wxTextCtrl(this, PARAMETER_DIALOG_PASSWORD_TEXT
, wxT(""), wxPoint(156, 209), wxSize( 140, 25), 0, wxDefaultValidator
, wxT("ParamPasswordTxt"));
1784 pParamDirPathMsg
= new wxStaticText(this, PARAMETER_DIALOG_DIRPATH_MSG
, wxT("Directory:"), wxPoint( 10, 243), wxSize( -1, -1), 0, wxT("ParamDirPathMsg"));
1785 pParamDirPathTxt
= new wxTextCtrl(this, PARAMETER_DIALOG_DIRPATH_TEXT
, wxT(""), wxPoint( 10, 259), wxSize(140, 25), 0, wxDefaultValidator
, wxT("ParamDirPathTxt"));
1786 pParamSaveBtn
= new wxButton(this, PARAMETER_DIALOG_SAVE
, wxT("&Save"), wxPoint(310, 21), wxSize( 70, 35), 0, wxDefaultValidator
, wxT("ParamSaveBtn"));
1787 pParamCancelBtn
= new wxButton(this, PARAMETER_DIALOG_CANCEL
, wxT("C&ancel"), wxPoint(310, 66), wxSize( 70, 35), 0, wxDefaultValidator
, wxT("ParamCancelBtn"));
1789 // Now that all the widgets on the panel are created, its safe to allow ::OnCommand() to
1790 // handle all widget processing
1791 widgetPtrsSet
= TRUE
;
1794 savedParamSettings
= wxGetApp().params
;
1799 } // CparameterDlg constructor
1802 void CparameterDlg::OnCloseWindow(wxCloseEvent
& event
)
1804 // Put any additional checking necessary to make certain it is alright
1805 // to close the program here that is not done elsewhere
1808 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
);
1816 wxGetApp().params
= savedParamSettings
;
1819 if (GetParent() != NULL
)
1820 GetParent()->SetFocus();
1826 SetReturnCode(0); // added so BoundsChecker would not report use of uninitialized variable
1829 } // CparameterDlg::OnCloseWindow()
1832 void CparameterDlg::OnButton( wxCommandEvent
&event
)
1834 wxWindow
*win
= (wxWindow
*) event
.GetEventObject();
1835 OnCommand( *win
, event
);
1839 void CparameterDlg::OnCommand(wxWindow
& win
, wxCommandEvent
& event
)
1841 wxString widgetName
;
1843 widgetName
= win
.GetName();
1848 if (widgetName
== pParamSaveBtn
->GetName())
1853 tStr
= wxT("Database parameters have been saved.");
1854 if (GetParent() != NULL
) // The parameter dialog was not called during startup due to a missing cfg file
1855 tStr
+= wxT("\nNew parameters will take effect the next time the program is started.");
1856 wxMessageBox(tStr
,wxT("Notice..."),wxOK
| wxICON_INFORMATION
);
1863 if (widgetName
== pParamCancelBtn
->GetName())
1868 } // CparameterDlg::OnCommand()
1871 bool CparameterDlg::PutData()
1873 // Fill the data source list box
1874 FillDataSourceList();
1876 // Fill in the fields from the params object
1877 if (wxGetApp().params
.ODBCSource
&& wxStrlen(wxGetApp().params
.ODBCSource
))
1878 pParamODBCSourceList
->SetStringSelection(wxGetApp().params
.ODBCSource
);
1879 pParamUserNameTxt
->SetValue(wxGetApp().params
.UserName
);
1880 pParamPasswordTxt
->SetValue(wxGetApp().params
.Password
);
1881 pParamDirPathTxt
->SetValue(wxGetApp().params
.DirPath
);
1883 } // CparameterDlg::PutData()
1886 bool CparameterDlg::GetData()
1889 if (pParamODBCSourceList
->GetStringSelection() != wxT(""))
1891 tStr
= pParamODBCSourceList
->GetStringSelection();
1892 if (tStr
.Length() > (sizeof(wxGetApp().params
.ODBCSource
)-1))
1895 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());
1896 wxMessageBox(errmsg
,wxT("Internal program error..."),wxOK
| wxICON_EXCLAMATION
);
1899 wxStrcpy(wxGetApp().params
.ODBCSource
, tStr
);
1904 tStr
= pParamUserNameTxt
->GetValue();
1905 if (tStr
.Length() > (sizeof(wxGetApp().params
.UserName
)-1))
1908 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());
1909 wxMessageBox(errmsg
,wxT("Internal program error..."),wxOK
| wxICON_EXCLAMATION
);
1912 wxStrcpy(wxGetApp().params
.UserName
, tStr
);
1914 tStr
= pParamPasswordTxt
->GetValue();
1915 if (tStr
.Length() > (sizeof(wxGetApp().params
.Password
)-1))
1918 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());
1919 wxMessageBox(errmsg
,wxT("Internal program error..."),wxOK
| wxICON_EXCLAMATION
);
1922 wxStrcpy(wxGetApp().params
.Password
,tStr
);
1924 tStr
= pParamDirPathTxt
->GetValue();
1925 tStr
.Replace(wxT("\\"),wxT("/"));
1926 if (tStr
.Length() > (sizeof(wxGetApp().params
.DirPath
)-1))
1929 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());
1930 wxMessageBox(errmsg
,wxT("Internal program error..."),wxOK
| wxICON_EXCLAMATION
);
1933 wxStrcpy(wxGetApp().params
.DirPath
,tStr
);
1935 } // CparameterDlg::GetData()
1938 bool CparameterDlg::Save()
1940 // Copy the current params in case user cancels changing
1941 // the params, so that we can reset them.
1944 wxGetApp().params
= savedParamSettings
;
1948 wxGetApp().WriteParamFile(wxGetApp().params
);
1951 } // CparameterDlg::Save()
1954 void CparameterDlg::FillDataSourceList()
1956 wxChar Dsn
[SQL_MAX_DSN_LENGTH
+ 1];
1958 wxStringList strList
;
1960 while (wxDbGetDataSource(wxGetApp().DbConnectInf
->GetHenv(), Dsn
,
1961 SQL_MAX_DSN_LENGTH
+1, DsDesc
, 255))
1965 strList
.Add(wxT(""));
1966 wxChar
**p
= strList
.ListToArray();
1969 for (i
= 0; wxStrlen(p
[i
]); i
++)
1970 pParamODBCSourceList
->Append(p
[i
]);
1973 } // CparameterDlg::FillDataSourceList()
1976 BEGIN_EVENT_TABLE(CqueryDlg
, wxDialog
)
1977 EVT_BUTTON(-1, CqueryDlg::OnButton
)
1978 EVT_CLOSE(CqueryDlg::OnCloseWindow
)
1982 // CqueryDlg() constructor
1983 CqueryDlg::CqueryDlg(wxWindow
*parent
, wxDb
*pDb
, wxChar
*tblName
[],
1984 const wxString
&pWhereArg
) :
1985 wxDialog (parent
, QUERY_DIALOG
, wxT("Query"), wxPoint(-1, -1), wxSize(480, 360))
1987 wxBeginBusyCursor();
1991 masterTableName
= tblName
[0];
1992 widgetPtrsSet
= FALSE
;
1995 // Initialize the WHERE clause from the string passed in
1996 pWhere
= pWhereArg
; // Save a pointer to the output buffer
1997 if (pWhere
.Length() > (unsigned int)DB_MAX_WHERE_CLAUSE_LEN
) // Check the length of the buffer passed in
2000 s
.Printf(wxT("Maximum where clause length exceeded.\nLength must be less than %d"), DB_MAX_WHERE_CLAUSE_LEN
+1);
2001 wxMessageBox(s
,wxT("Error..."),wxOK
| wxICON_EXCLAMATION
);
2006 pQueryCol1Msg
= new wxStaticText(this, QUERY_DIALOG_COL_MSG
, wxT("Column 1:"), wxPoint( 10, 10), wxSize( 69, 16), 0, wxT("QueryCol1Msg"));
2007 pQueryCol1Choice
= new wxChoice(this, QUERY_DIALOG_COL_CHOICE
, wxPoint( 10, 27), wxSize(250, 27), 0, 0, 0, wxDefaultValidator
, wxT("QueryCol1Choice"));
2008 pQueryNotMsg
= new wxStaticText(this, QUERY_DIALOG_NOT_MSG
, wxT("NOT"), wxPoint(268, 10), wxSize( -1, -1), 0, wxT("QueryNotMsg"));
2009 pQueryNotCheck
= new wxCheckBox(this, QUERY_DIALOG_NOT_CHECKBOX
, wxT(""), wxPoint(275, 37), wxSize( 20, 20), 0, wxDefaultValidator
, wxT("QueryNotCheck"));
2011 wxString choice_strings
[9];
2012 choice_strings
[0] = wxT("=");
2013 choice_strings
[1] = wxT("<");
2014 choice_strings
[2] = wxT(">");
2015 choice_strings
[3] = wxT("<=");
2016 choice_strings
[4] = wxT(">=");
2017 choice_strings
[5] = wxT("Begins");
2018 choice_strings
[6] = wxT("Contains");
2019 choice_strings
[7] = wxT("Like");
2020 choice_strings
[8] = wxT("Between");
2022 pQueryOperatorMsg
= new wxStaticText(this, QUERY_DIALOG_OP_MSG
, wxT("Operator:"), wxPoint(305, 10), wxSize( -1, -1), 0, wxT("QueryOperatorMsg"));
2023 pQueryOperatorChoice
= new wxChoice(this, QUERY_DIALOG_OP_CHOICE
, wxPoint(305, 27), wxSize( 80, 27), 9, choice_strings
, 0, wxDefaultValidator
, wxT("QueryOperatorChoice"));
2024 pQueryCol2Msg
= new wxStaticText(this, QUERY_DIALOG_COL2_MSG
, wxT("Column 2:"), wxPoint( 10, 65), wxSize( 69, 16), 0, wxT("QueryCol2Msg"));
2025 pQueryCol2Choice
= new wxChoice(this, QUERY_DIALOG_COL2_CHOICE
, wxPoint( 10, 82), wxSize(250, 27), 0, 0, 0, wxDefaultValidator
, wxT("QueryCol2Choice"));
2026 pQuerySqlWhereMsg
= new wxStaticText(this, QUERY_DIALOG_WHERE_MSG
, wxT("SQL where clause:"), wxPoint( 10, 141), wxSize( -1, -1), 0, wxT("QuerySqlWhereMsg"));
2027 pQuerySqlWhereMtxt
= new wxTextCtrl(this, QUERY_DIALOG_WHERE_TEXT
, wxT(""), wxPoint( 10, 159), wxSize(377, 134), wxTE_MULTILINE
, wxDefaultValidator
, wxT("QuerySqlWhereMtxt"));
2028 pQueryAddBtn
= new wxButton(this, QUERY_DIALOG_ADD
, wxT("&Add"), wxPoint(406, 24), wxSize( 56, 26), 0, wxDefaultValidator
, wxT("QueryAddBtn"));
2029 pQueryAndBtn
= new wxButton(this, QUERY_DIALOG_AND
, wxT("A&nd"), wxPoint(406, 58), wxSize( 56, 26), 0, wxDefaultValidator
, wxT("QueryAndBtn"));
2030 pQueryOrBtn
= new wxButton(this, QUERY_DIALOG_OR
, wxT("&Or"), wxPoint(406, 92), wxSize( 56, 26), 0, wxDefaultValidator
, wxT("QueryOrBtn"));
2031 pQueryLParenBtn
= new wxButton(this, QUERY_DIALOG_LPAREN
, wxT("("), wxPoint(406, 126), wxSize( 26, 26), 0, wxDefaultValidator
, wxT("QueryLParenBtn"));
2032 pQueryRParenBtn
= new wxButton(this, QUERY_DIALOG_RPAREN
, wxT(")"), wxPoint(436, 126), wxSize( 26, 26), 0, wxDefaultValidator
, wxT("QueryRParenBtn"));
2033 pQueryDoneBtn
= new wxButton(this, QUERY_DIALOG_DONE
, wxT("&Done"), wxPoint(406, 185), wxSize( 56, 26), 0, wxDefaultValidator
, wxT("QueryDoneBtn"));
2034 pQueryClearBtn
= new wxButton(this, QUERY_DIALOG_CLEAR
, wxT("C&lear"), wxPoint(406, 218), wxSize( 56, 26), 0, wxDefaultValidator
, wxT("QueryClearBtn"));
2035 pQueryCountBtn
= new wxButton(this, QUERY_DIALOG_COUNT
, wxT("&Count"), wxPoint(406, 252), wxSize( 56, 26), 0, wxDefaultValidator
, wxT("QueryCountBtn"));
2036 pQueryValue1Msg
= new wxStaticText(this, QUERY_DIALOG_VALUE1_MSG
, wxT("Value:"), wxPoint(277, 66), wxSize( -1, -1), 0, wxT("QueryValue1Msg"));
2037 pQueryValue1Txt
= new wxTextCtrl(this, QUERY_DIALOG_VALUE1_TEXT
, wxT(""), wxPoint(277, 83), wxSize(108, 25), 0, wxDefaultValidator
, wxT("QueryValue1Txt"));
2038 pQueryValue2Msg
= new wxStaticText(this, QUERY_DIALOG_VALUE2_MSG
, wxT("AND"), wxPoint(238, 126), wxSize( -1, -1), 0, wxT("QueryValue2Msg"));
2039 pQueryValue2Txt
= new wxTextCtrl(this, QUERY_DIALOG_VALUE2_TEXT
, wxT(""), wxPoint(277, 120), wxSize(108, 25), 0, wxDefaultValidator
, wxT("QueryValue2Txt"));
2040 pQueryHintGrp
= new wxStaticBox(this, QUERY_DIALOG_HINT_GROUP
, wxT(""), wxPoint( 10, 291), wxSize(377, 40), 0, wxT("QueryHintGrp"));
2041 pQueryHintMsg
= new wxStaticText(this, QUERY_DIALOG_HINT_MSG
, wxT(""), wxPoint( 16, 306), wxSize( -1, -1), 0, wxT("QueryHintMsg"));
2043 widgetPtrsSet
= TRUE
;
2044 // Initialize the dialog
2046 pQueryCol2Choice
->Append(wxT("VALUE -->"));
2047 colInf
= pDB
->GetColumns(tblName
);
2053 tStr
= wxT("ODBC error during GetColumns()\n\n");
2054 tStr
+= GetExtendedDBErrorMsg(pDb
,__FILE__
,__LINE__
);
2055 wxMessageBox(tStr
,wxT("ODBC Error..."),wxOK
| wxICON_EXCLAMATION
);
2060 for (i
= 0; colInf
[i
].colName
&& wxStrlen(colInf
[i
].colName
); i
++)
2062 // If there is more than one table being queried, qualify
2063 // the column names with the table name prefix.
2064 if (tblName
[1] && wxStrlen(tblName
[1]))
2066 qualName
.Printf(wxT("%s.%s"), colInf
[i
].tableName
, colInf
[i
].colName
);
2067 pQueryCol1Choice
->Append(qualName
);
2068 pQueryCol2Choice
->Append(qualName
);
2070 else // Single table query, append just the column names
2072 pQueryCol1Choice
->Append(colInf
[i
].colName
);
2073 pQueryCol2Choice
->Append(colInf
[i
].colName
);
2077 pQueryCol1Choice
->SetSelection(0);
2078 pQueryCol2Choice
->SetSelection(0);
2079 pQueryOperatorChoice
->SetSelection(0);
2081 pQueryValue2Msg
->Show(FALSE
);
2082 pQueryValue2Txt
->Show(FALSE
);
2084 pQueryHintMsg
->SetLabel(langQRY_EQ
);
2086 pQuerySqlWhereMtxt
->SetValue(pWhere
.c_str());
2090 // Display the dialog window
2093 } // CqueryDlg() constructor
2096 CqueryDlg::~CqueryDlg()
2098 } // CqueryDlg::~CqueryDlg() destructor
2101 void CqueryDlg::OnButton(wxCommandEvent
&event
)
2103 wxWindow
*win
= (wxWindow
*) event
.GetEventObject();
2104 OnCommand( *win
, event
);
2105 } // CqueryDlg::OnButton()
2108 void CqueryDlg::OnCommand(wxWindow
& win
, wxCommandEvent
& event
)
2110 // Widget pointers won't be set when the dialog is constructed.
2111 // Control is passed through this function once for each widget on
2112 // a dialog as the dialog is constructed.
2116 wxString widgetName
= win
.GetName();
2118 // Operator choice box
2119 if (widgetName
== pQueryOperatorChoice
->GetName())
2121 // Set the help text
2122 switch((qryOp
) pQueryOperatorChoice
->GetSelection())
2125 pQueryHintMsg
->SetLabel(langQRY_EQ
);
2128 pQueryHintMsg
->SetLabel(langQRY_LT
);
2131 pQueryHintMsg
->SetLabel(langQRY_GT
);
2134 pQueryHintMsg
->SetLabel(langQRY_LE
);
2137 pQueryHintMsg
->SetLabel(langQRY_GE
);
2140 pQueryHintMsg
->SetLabel(langQRY_BEGINS
);
2143 pQueryHintMsg
->SetLabel(langQRY_CONTAINS
);
2146 pQueryHintMsg
->SetLabel(langQRY_LIKE
);
2149 pQueryHintMsg
->SetLabel(langQRY_BETWEEN
);
2153 // Hide the value2 widget
2154 pQueryValue2Msg
->Show(FALSE
); // BETWEEN will show this widget
2155 pQueryValue2Txt
->Show(FALSE
); // BETWEEN will show this widget
2157 // Disable the NOT operator for <, <=, >, >=
2158 switch((qryOp
) pQueryOperatorChoice
->GetSelection())
2164 pQueryNotCheck
->SetValue(0);
2165 pQueryNotCheck
->Enable(FALSE
);
2168 pQueryNotCheck
->Enable(TRUE
);
2172 // Manipulate the dialog to handle the selected operator
2173 switch((qryOp
) pQueryOperatorChoice
->GetSelection())
2180 pQueryCol2Choice
->Enable(TRUE
);
2181 if (pQueryCol2Choice
->GetSelection()) // Column name is highlighted
2183 pQueryValue1Msg
->Show(FALSE
);
2184 pQueryValue1Txt
->Show(FALSE
);
2186 else // "Value" is highlighted
2188 pQueryValue1Msg
->Show(TRUE
);
2189 pQueryValue1Txt
->Show(TRUE
);
2190 pQueryValue1Txt
->SetFocus();
2196 pQueryCol2Choice
->SetSelection(0);
2197 pQueryCol2Choice
->Enable(FALSE
);
2198 pQueryValue1Msg
->Show(TRUE
);
2199 pQueryValue1Txt
->Show(TRUE
);
2200 pQueryValue1Txt
->SetFocus();
2203 pQueryCol2Choice
->SetSelection(0);
2204 pQueryCol2Choice
->Enable(FALSE
);
2205 pQueryValue2Msg
->Show(TRUE
);
2206 pQueryValue2Txt
->Show(TRUE
);
2207 pQueryValue1Msg
->Show(TRUE
);
2208 pQueryValue1Txt
->Show(TRUE
);
2209 pQueryValue1Txt
->SetFocus();
2215 } // Operator choice box
2218 if (widgetName
== pQueryCol2Choice
->GetName())
2220 if (pQueryCol2Choice
->GetSelection()) // Column name is highlighted
2222 pQueryValue1Msg
->Show(FALSE
);
2223 pQueryValue1Txt
->Show(FALSE
);
2225 else // "Value" is highlighted
2227 pQueryValue1Msg
->Show(TRUE
);
2228 pQueryValue1Txt
->Show(TRUE
);
2229 pQueryValue1Txt
->SetFocus();
2232 } // Column 2 choice
2235 if (widgetName
== pQueryAddBtn
->GetName())
2242 if (widgetName
== pQueryAndBtn
->GetName())
2244 AppendToWhere(wxT(" AND\n"));
2249 if (widgetName
== pQueryOrBtn
->GetName())
2251 AppendToWhere(wxT(" OR\n"));
2255 // Left Paren button
2256 if (widgetName
== pQueryLParenBtn
->GetName())
2258 AppendToWhere(wxT("("));
2260 } // Left Paren button
2262 // Right paren button
2263 if (widgetName
== pQueryRParenBtn
->GetName())
2265 AppendToWhere(wxT(")"));
2267 } // Right Paren button
2270 if (widgetName
== pQueryDoneBtn
->GetName())
2272 // Be sure the where clause will not overflow the output buffer
2273 if (wxStrlen(pQuerySqlWhereMtxt
->GetValue()) > (unsigned int)DB_MAX_WHERE_CLAUSE_LEN
)
2276 s
.Printf(wxT("Maximum where clause length exceeded.\nLength must be less than %d"), DB_MAX_WHERE_CLAUSE_LEN
+1);
2277 wxMessageBox(s
,wxT("Error..."),wxOK
| wxICON_EXCLAMATION
);
2280 // Validate the where clause for things such as matching parens
2281 if (!ValidateWhereClause())
2283 // Copy the where clause to the output buffer and exit
2284 pWhere
= pQuerySqlWhereMtxt
->GetValue();
2290 if (widgetName
== pQueryClearBtn
->GetName())
2292 bool Ok
= (wxMessageBox(wxT("Are you sure you wish to clear the Query?"),wxT("Confirm"),wxYES_NO
|wxICON_QUESTION
) == wxYES
);
2295 pQuerySqlWhereMtxt
->SetValue(wxT(""));
2300 if (widgetName
== pQueryCountBtn
->GetName())
2302 wxBeginBusyCursor();
2308 } // CqueryDlg::OnCommand
2311 void CqueryDlg::OnCloseWindow(wxCloseEvent
& event
)
2318 GetParent()->SetFocus();
2323 SetReturnCode(1); // added so BoundsChecker would not report use of uninitialized variable
2326 } // CqueryDlg::OnCloseWindow()
2329 void CqueryDlg::AppendToWhere(wxChar
*s
)
2331 wxString whereStr
= pQuerySqlWhereMtxt
->GetValue();
2333 pQuerySqlWhereMtxt
->SetValue(whereStr
);
2334 } // CqueryDlg::AppendToWhere()
2337 void CqueryDlg::ProcessAddBtn()
2339 qryOp oper
= (qryOp
) pQueryOperatorChoice
->GetSelection();
2341 // Verify that eveything is filled in correctly
2342 if (pQueryCol2Choice
->GetSelection() == 0) // "Value" is selected
2344 // Verify that value 1 is filled in
2345 if (wxStrlen(pQueryValue1Txt
->GetValue()) == 0)
2348 pQueryValue1Txt
->SetFocus();
2351 // For the BETWEEN operator, value 2 must be filled in as well
2352 if (oper
== qryOpBETWEEN
&&
2353 wxStrlen(pQueryValue2Txt
->GetValue()) == 0)
2356 pQueryValue2Txt
->SetFocus();
2361 // Build the expression and append it to the where clause window
2362 wxString s
= pQueryCol1Choice
->GetStringSelection();
2364 if (pQueryNotCheck
->GetValue() && (oper
!= qryOpEQ
))
2370 if (pQueryNotCheck
->GetValue()) // NOT box is checked
2393 s
+= wxT(" BETWEEN");
2399 int col1Idx
= pQueryCol1Choice
->GetSelection();
2402 if (colInf
[col1Idx
].sqlDataType
== SQL_VARCHAR
||
2403 oper
== qryOpBEGINS
||
2404 oper
== qryOpCONTAINS
||
2408 if (pQueryCol2Choice
->GetSelection()) // Column name
2409 s
+= pQueryCol2Choice
->GetStringSelection();
2410 else // Column 2 is a "value"
2414 if (oper
== qryOpCONTAINS
)
2416 s
+= pQueryValue1Txt
->GetValue();
2417 if (oper
== qryOpCONTAINS
|| oper
== qryOpBEGINS
)
2423 if (oper
== qryOpBETWEEN
)
2428 s
+= pQueryValue2Txt
->GetValue();
2433 AppendToWhere((wxChar
*) (const wxChar
*) s
);
2435 } // CqueryDlg::ProcessAddBtn()
2438 void CqueryDlg::ProcessCountBtn()
2440 if (!ValidateWhereClause())
2443 if (!dbTable
) // wxDbTable object needs to be created and opened
2445 dbTable
= new wxDbTable(pDB
, masterTableName
, 0, wxT(""),
2447 wxGetApp().DbConnectInf
->GetDefaultDir());
2450 wxMessageBox(wxT("Memory allocation failed creating a wxDbTable object."),wxT("Error..."),wxOK
| wxICON_EXCLAMATION
);
2453 if (!dbTable
->Open())
2456 tStr
= wxT("ODBC error during Open()\n\n");
2457 tStr
+= GetExtendedDBErrorMsg(dbTable
->GetDb(),__FILE__
,__LINE__
);
2458 wxMessageBox(tStr
,wxT("ODBC Error..."),wxOK
| wxICON_EXCLAMATION
);
2463 // Count() with WHERE clause
2466 whereStr
= pQuerySqlWhereMtxt
->GetValue();
2467 dbTable
->SetWhereClause(whereStr
.c_str());
2469 ULONG whereCnt
= dbTable
->Count();
2471 // Count() of all records in the table
2472 dbTable
->SetWhereClause(wxT(""));
2473 ULONG totalCnt
= dbTable
->Count();
2475 if (whereCnt
> 0 || totalCnt
== 0)
2478 tStr
.Printf(wxT("%lu of %lu records match the query criteria."),whereCnt
,totalCnt
);
2479 wxMessageBox(tStr
,wxT("Notice..."),wxOK
| wxICON_INFORMATION
);
2484 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
);
2485 wxMessageBox(tStr
,wxT("Notice..."),wxOK
| wxICON_INFORMATION
);
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
2493 } // CqueryDlg::ProcessCountBtn()
2496 bool CqueryDlg::ValidateWhereClause()
2498 wxString where
= pQuerySqlWhereMtxt
->GetValue();
2500 if (where
.Freq(wxT('(')) != where
.Freq(wxT(')')))
2502 wxMessageBox(wxT("There are mismatched parenthesis in the constructed where clause"),wxT("Error..."),wxOK
| wxICON_EXCLAMATION
);
2505 // After a wxMessageBox, the focus does not necessarily return to the
2506 // window which was the focus when the message box popped up, so return
2507 // focus to the Query dialog for certain
2512 } // CqueryDlg::ValidateWhereClause()
2516 void DisplayDbDiagnostics(wxDb
*pDb
)
2521 s
= langDBINF_DB_NAME
;
2522 s
+= pDb
->dbInf
.dbmsName
;
2525 s
+= langDBINF_DB_VER
;
2526 s
+= pDb
->dbInf
.dbmsVer
;
2529 s
+= langDBINF_DRIVER_NAME
;
2530 s
+= pDb
->dbInf
.driverName
;
2533 s
+= langDBINF_DRIVER_ODBC_VER
;
2534 s
+= pDb
->dbInf
.odbcVer
;
2537 s
+= langDBINF_DRIVER_MGR_ODBC_VER
;
2538 s
+= pDb
->dbInf
.drvMgrOdbcVer
;
2541 s
+= langDBINF_DRIVER_VER
;
2542 s
+= pDb
->dbInf
.driverVer
;
2545 s
+= langDBINF_SERVER_NAME
;
2546 s
+= pDb
->dbInf
.serverName
;
2549 s
+= langDBINF_FILENAME
;
2550 s
+= pDb
->dbInf
.databaseName
;
2553 s
+= langDBINF_OUTER_JOINS
;
2554 s
+= pDb
->dbInf
.outerJoins
;
2557 s
+= langDBINF_STORED_PROC
;
2558 s
+= pDb
->dbInf
.procedureSupport
;
2561 if (pDb
->dbInf
.maxConnections
)
2562 t
.sprintf("%s%d\n", langDBINF_MAX_HDBC
, pDb
->dbInf
.maxConnections
);
2564 t
.sprintf("%s%s\n", langDBINF_MAX_HDBC
, langDBINF_UNLIMITED
);
2567 if (pDb
->dbInf
.maxStmts
)
2568 t
.sprintf("%s%d\n", langDBINF_MAX_HSTMT
, pDb
->dbInf
.maxStmts
);
2570 t
.sprintf("%s%s\n", langDBINF_MAX_HSTMT
, langDBINF_UNLIMITED
);
2573 s
+= langDBINF_API_LVL
;
2574 switch(pDb
->dbInf
.apiConfLvl
)
2576 case SQL_OAC_NONE
: s
+= langDBINF_NONE
; break;
2577 case SQL_OAC_LEVEL1
: s
+= langDBINF_LEVEL1
; break;
2578 case SQL_OAC_LEVEL2
: s
+= langDBINF_LEVEL2
; break;
2582 s
+= langDBINF_CLI_LVL
;
2583 switch(pDb
->dbInf
.cliConfLvl
)
2585 case SQL_OSCC_NOT_COMPLIANT
: s
+= langDBINF_NOT_COMPLIANT
; break;
2586 case SQL_OSCC_COMPLIANT
: s
+= langDBINF_COMPLIANT
; break;
2590 s
+= langDBINF_SQL_LVL
;
2591 switch(pDb
->dbInf
.sqlConfLvl
)
2593 case SQL_OSC_MINIMUM
: s
+= langDBINF_MIN_GRAMMAR
; break;
2594 case SQL_OSC_CORE
: s
+= langDBINF_CORE_GRAMMAR
; break;
2595 case SQL_OSC_EXTENDED
: s
+= langDBINF_EXT_GRAMMAR
; break;
2599 s
+= langDBINF_COMMIT_BEHAVIOR
;
2600 switch(pDb
->dbInf
.cursorCommitBehavior
)
2602 case SQL_CB_DELETE
: s
+= langDBINF_DELETE_CURSORS
; break;
2603 case SQL_CB_CLOSE
: s
+= langDBINF_CLOSE_CURSORS
; break;
2604 case SQL_CB_PRESERVE
: s
+= langDBINF_PRESERVE_CURSORS
; break;
2608 s
+= langDBINF_ROLLBACK_BEHAVIOR
;
2609 switch(pDb
->dbInf
.cursorRollbackBehavior
)
2611 case SQL_CB_DELETE
: s
+= langDBINF_DELETE_CURSORS
; break;
2612 case SQL_CB_CLOSE
: s
+= langDBINF_CLOSE_CURSORS
; break;
2613 case SQL_CB_PRESERVE
: s
+= langDBINF_PRESERVE_CURSORS
; break;
2617 s
+= langDBINF_SUPP_NOT_NULL
;
2618 switch(pDb
->dbInf
.supportNotNullClause
)
2620 case SQL_NNC_NULL
: s
+= langNO
; break;
2621 case SQL_NNC_NON_NULL
: s
+= langYES
; break;
2625 s
+= langDBINF_SUPP_IEF
;
2626 s
+= pDb
->dbInf
.supportIEF
;
2629 // DEFAULT setting for "Transaction Isolation Level"
2630 s
+= langDBINF_TXN_ISOLATION
;
2631 switch(pDb
->dbInf
.txnIsolation
)
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;
2643 // CURRENT setting for "Transaction Isolation Level"
2645 s
+= langDBINF_TXN_ISOLATION_CURR
;
2646 if (SQLGetConnectOption(pDb
->GetHDBC(),SQL_TXN_ISOLATION
,&txnIsoLvl
) == SQL_SUCCESS
)
2650 case SQL_TXN_READ_UNCOMMITTED
: s
+= langDBINF_READ_UNCOMMITTED
; break;
2651 case SQL_TXN_READ_COMMITTED
: s
+= langDBINF_READ_COMMITTED
; break;
2652 case SQL_TXN_REPEATABLE_READ
: s
+= langDBINF_REPEATABLE_READ
; break;
2653 case SQL_TXN_SERIALIZABLE
: s
+= langDBINF_SERIALIZABLE
; break;
2655 case SQL_TXN_VERSIONING
: s
+= langDBINF_VERSIONING
; break;
2662 s
+= langDBINF_TXN_ISOLATION_OPTS
;
2663 if (pDb
->dbInf
.txnIsolationOptions
& SQL_TXN_READ_UNCOMMITTED
)
2664 {s
+= langDBINF_READ_UNCOMMITTED
; comma
++;}
2665 if (pDb
->dbInf
.txnIsolationOptions
& SQL_TXN_READ_COMMITTED
)
2666 {if (comma
++) s
+= ", "; s
+= langDBINF_READ_COMMITTED
;}
2667 if (pDb
->dbInf
.txnIsolationOptions
& SQL_TXN_REPEATABLE_READ
)
2668 {if (comma
++) s
+= ", "; s
+= langDBINF_REPEATABLE_READ
;}
2669 if (pDb
->dbInf
.txnIsolationOptions
& SQL_TXN_SERIALIZABLE
)
2670 {if (comma
++) s
+= ", "; s
+= langDBINF_SERIALIZABLE
;}
2672 if (pDb
->dbInf
.txnIsolationOptions
& SQL_TXN_VERSIONING
)
2673 {if (comma
++) s
+= ", "; s
+= langDBINF_VERSIONING
;}
2678 s
+= langDBINF_FETCH_DIRS
;
2679 if (pDb
->dbInf
.fetchDirections
& SQL_FD_FETCH_NEXT
)
2680 {s
+= langDBINF_NEXT
; comma
++;}
2681 if (pDb
->dbInf
.fetchDirections
& SQL_FD_FETCH_PRIOR
)
2682 {if (comma
++) s
+= ", "; s
+= langDBINF_PREV
;}
2683 if (pDb
->dbInf
.fetchDirections
& SQL_FD_FETCH_FIRST
)
2684 {if (comma
++) s
+= ", "; s
+= langDBINF_FIRST
;}
2685 if (pDb
->dbInf
.fetchDirections
& SQL_FD_FETCH_LAST
)
2686 {if (comma
++) s
+= ", "; s
+= langDBINF_LAST
;}
2687 if (pDb
->dbInf
.fetchDirections
& SQL_FD_FETCH_ABSOLUTE
)
2688 {if (comma
++) s
+= ", "; s
+= langDBINF_ABSOLUTE
;}
2689 if (pDb
->dbInf
.fetchDirections
& SQL_FD_FETCH_RELATIVE
)
2690 {if (comma
++) s
+= ", "; s
+= langDBINF_RELATIVE
;}
2692 if (pDb
->dbInf
.fetchDirections
& SQL_FD_FETCH_RESUME
)
2693 {if (comma
++) s
+= ", "; s
+= langDBINF_RESUME
;}
2695 if (pDb
->dbInf
.fetchDirections
& SQL_FD_FETCH_BOOKMARK
)
2696 {if (comma
++) s
+= ", "; s
+= langDBINF_BOOKMARK
;}
2700 s
+= langDBINF_LOCK_TYPES
;
2701 if (pDb
->dbInf
.lockTypes
& SQL_LCK_NO_CHANGE
)
2702 {s
+= langDBINF_NO_CHANGE
; comma
++;}
2703 if (pDb
->dbInf
.lockTypes
& SQL_LCK_EXCLUSIVE
)
2704 {if (comma
++) s
+= ", "; s
+= langDBINF_EXCLUSIVE
;}
2705 if (pDb
->dbInf
.lockTypes
& SQL_LCK_UNLOCK
)
2706 {if (comma
++) s
+= ", "; s
+= langDBINF_UNLOCK
;}
2710 s
+= langDBINF_POS_OPERS
;
2711 if (pDb
->dbInf
.posOperations
& SQL_POS_POSITION
)
2712 {s
+= langDBINF_POSITION
; comma
++;}
2713 if (pDb
->dbInf
.posOperations
& SQL_POS_REFRESH
)
2714 {if (comma
++) s
+= ", "; s
+= langDBINF_REFRESH
;}
2715 if (pDb
->dbInf
.posOperations
& SQL_POS_UPDATE
)
2716 {if (comma
++) s
+= ", "; s
+= langDBINF_UPD
;}
2717 if (pDb
->dbInf
.posOperations
& SQL_POS_DELETE
)
2718 {if (comma
++) s
+= ", "; s
+= langDBINF_DEL
;}
2719 if (pDb
->dbInf
.posOperations
& SQL_POS_ADD
)
2720 {if (comma
++) s
+= ", "; s
+= langDBINF_ADD
;}
2724 s
+= langDBINF_POS_STMTS
;
2725 if (pDb
->dbInf
.posStmts
& SQL_PS_POSITIONED_DELETE
)
2726 {s
+= langDBINF_POS_DEL
; comma
++;}
2727 if (pDb
->dbInf
.posStmts
& SQL_PS_POSITIONED_UPDATE
)
2728 {if (comma
++) s
+= ", "; s
+= langDBINF_POS_UPD
;}
2729 if (pDb
->dbInf
.posStmts
& SQL_PS_SELECT_FOR_UPDATE
)
2730 {if (comma
++) s
+= ", "; s
+= langDBINF_SELECT_FOR_UPD
;}
2734 s
+= langDBINF_SCROLL_CONCURR
;
2735 if (pDb
->dbInf
.scrollConcurrency
& SQL_SCCO_READ_ONLY
)
2736 {s
+= langDBINF_READ_ONLY
; comma
++;}
2737 if (pDb
->dbInf
.scrollConcurrency
& SQL_SCCO_LOCK
)
2738 {if (comma
++) s
+= ", "; s
+= langDBINF_LOCK
;}
2739 if (pDb
->dbInf
.scrollConcurrency
& SQL_SCCO_OPT_ROWVER
)
2740 {if (comma
++) s
+= ", "; s
+= langDBINF_OPT_ROWVER
;}
2741 if (pDb
->dbInf
.scrollConcurrency
& SQL_SCCO_OPT_VALUES
)
2742 {if (comma
++) s
+= ", "; s
+= langDBINF_OPT_VALUES
;}
2746 s
+= langDBINF_SCROLL_OPTS
;
2747 if (pDb
->dbInf
.scrollOptions
& SQL_SO_FORWARD_ONLY
)
2748 {s
+= langDBINF_FWD_ONLY
; comma
++;}
2749 if (pDb
->dbInf
.scrollOptions
& SQL_SO_STATIC
)
2750 {if (comma
++) s
+= ", "; s
+= langDBINF_STATIC
;}
2751 if (pDb
->dbInf
.scrollOptions
& SQL_SO_KEYSET_DRIVEN
)
2752 {if (comma
++) s
+= ", "; s
+= langDBINF_KEYSET_DRIVEN
;}
2753 if (pDb
->dbInf
.scrollOptions
& SQL_SO_DYNAMIC
)
2754 {if (comma
++) s
+= ", "; s
+= langDBINF_DYNAMIC
;}
2755 if (pDb
->dbInf
.scrollOptions
& SQL_SO_MIXED
)
2756 {if (comma
++) s
+= ", "; s
+= langDBINF_MIXED
;}
2760 s
+= langDBINF_STATIC_SENS
;
2761 if (pDb
->dbInf
.staticSensitivity
& SQL_SS_ADDITIONS
)
2762 {s
+= langDBINF_ADDITIONS
; comma
++;}
2763 if (pDb
->dbInf
.staticSensitivity
& SQL_SS_DELETIONS
)
2764 {if (comma
++) s
+= ", "; s
+= langDBINF_DELETIONS
;}
2765 if (pDb
->dbInf
.staticSensitivity
& SQL_SS_UPDATES
)
2766 {if (comma
++) s
+= ", "; s
+= langDBINF_UPDATES
;}
2770 s
+= langDBINF_TXN_CAPABLE
;
2771 switch(pDb
->dbInf
.txnCapable
)
2773 case SQL_TC_NONE
: s
+= langNO
; break;
2774 case SQL_TC_DML
: s
+= langDBINF_DML_ONLY
; break;
2775 case SQL_TC_DDL_COMMIT
: s
+= langDBINF_DDL_COMMIT
; break;
2776 case SQL_TC_DDL_IGNORE
: s
+= langDBINF_DDL_IGNORE
; break;
2777 case SQL_TC_ALL
: s
+= langDBINF_DDL_AND_DML
; break;
2781 t
.sprintf("%s%d\n", langDBINF_LOGIN_TIMEOUT
, pDb
->dbInf
.loginTimeout
);
2784 // Oracle specific information
2785 if (pDb
->Dbms() == dbmsORACLE
)
2788 s
+= langDBINF_ORACLE_BANNER
;
2791 // Oracle cache hit ratio
2794 pDb
->ExecSql("SELECT VALUE FROM V$SYSSTAT WHERE NAME = 'db block gets'");
2796 if (pDb
->GetData(1, SQL_C_ULONG
, &dbBlockGets
, 0, &cb
))
2798 t
.sprintf("%s: %lu\n", langDBINF_DB_BLOCK_GETS
, dbBlockGets
);
2802 ULONG consistentGets
;
2803 pDb
->ExecSql("SELECT VALUE FROM V$SYSSTAT WHERE NAME = 'consistent gets'");
2805 if (pDb
->GetData(1, SQL_C_ULONG
, &consistentGets
, 0, &cb
))
2807 t
.sprintf("%s: %lu\n", langDBINF_CONSISTENT_GETS
, consistentGets
);
2812 pDb
->ExecSql("SELECT VALUE FROM V$SYSSTAT WHERE NAME = 'physical reads'");
2814 if (pDb
->GetData(1, SQL_C_ULONG
, &physReads
, 0, &cb
))
2816 t
.sprintf("%s: %lu\n", langDBINF_PHYSICAL_READS
, physReads
);
2820 ULONG hitRatio
= (ULONG
)((1.00 - ((float)physReads
/ (float)(dbBlockGets
+ consistentGets
))) * 100.00);
2821 t
.sprintf("*** %s: %lu%%\n", langDBINF_CACHE_HIT_RATIO
, hitRatio
);
2824 // Tablespace information
2826 s
+= langDBINF_TABLESPACE_IO
;
2829 char tablespaceName
[257];
2830 pDb
->ExecSql("SELECT NAME,PHYRDS,PHYWRTS FROM V$DATAFILE, V$FILESTAT WHERE V$DATAFILE.FILE# = V$FILESTAT.FILE#");
2831 while (pDb
->GetNext())
2833 pDb
->GetData(1, SQL_C_CHAR
, tablespaceName
, 257, &cb
);
2834 pDb
->GetData(2, SQL_C_ULONG
, &physReads
, 0, &cb
);
2835 pDb
->GetData(3, SQL_C_ULONG
, &physWrites
, 0, &cb
);
2836 t
.sprintf("%s\n\t%s: %lu\t%s: %lu\n", tablespaceName
,
2837 langDBINF_PHYSICAL_READS
, physReads
, langDBINF_PHYSICAL_WRITES
, physWrites
);
2846 } // DisplayDbDiagnostics()
2852 TEST CODE FOR TESTING THE wxDbCreateDataSource() FUNCTION
2855 result = wxDbCreateDataSource(wxT("Microsoft Access Driver (*.mdb)"),wxT("GLT-TEST2"),wxT("GLT-Descrip"),FALSE,wxT(""),this);
2858 // check for errors caused by ConfigDSN based functions
2861 wxChar errMsg[500+1];
2862 errMsg[0] = wxT('\0');
2864 SQLInstallerError(1,&retcode,errMsg,500,&cb);
2866 wxMessageBox(wxT("FAILED creating data source"),wxT("FAILED"));
2869 wxMessageBox(wxT("SUCCEEDED creating data source"),wxT("SUCCESS"));