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(recreate
))
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 wxGetApp().Contact
->GetDb()->RollbackTrans(); // Make sure the current cursor is in a known/stable state
620 if (!wxGetApp().Contact
->CreateIndexes(true))
625 tStr
= wxT("Error creating CONTACTS indexes.\nNew indexes will be unavailable.\n\n");
626 tStr
+= GetExtendedDBErrorMsg(wxGetApp().Contact
->GetDb(),__FILE__
,__LINE__
);
627 wxMessageBox(tStr
,wxT("ODBC Error..."),wxOK
| wxICON_EXCLAMATION
);
630 wxMessageBox(wxT("Index(es) were successfully recreated."),wxT("Notice..."),wxOK
| wxICON_INFORMATION
);
632 } // DatabaseDemoFrame::OnRecreateIndexes()
635 void DatabaseDemoFrame::OnExit(wxCommandEvent
& event
)
638 } // DatabaseDemoFrame::OnExit()
641 void DatabaseDemoFrame::OnEditParameters(wxCommandEvent
& event
)
643 if ((pEditorDlg
->mode
!= mCreate
) && (pEditorDlg
->mode
!= mEdit
))
644 BuildParameterDialog(this);
646 wxMessageBox(wxT("Cannot change database parameters while creating or editing a record"),wxT("Notice..."),wxOK
| wxICON_INFORMATION
);
647 } // DatabaseDemoFrame::OnEditParameters()
650 void DatabaseDemoFrame::OnAbout(wxCommandEvent
& event
)
652 wxMessageBox(wxT("wxWindows sample program for database classes\n\nContributed on 27 July 1998"),wxT("About..."),wxOK
| wxICON_INFORMATION
);
653 } // DatabaseDemoFrame::OnAbout()
656 // Put any additional checking necessary to make certain it is alright
657 // to close the program here that is not done elsewhere
658 void DatabaseDemoFrame::OnCloseWindow(wxCloseEvent
& event
)
661 if (pEditorDlg
&& pEditorDlg
->Close())
672 wxDELETE(wxGetApp().Contact
);
674 // This function will close all the connections to the database that have been
675 // previously cached.
676 wxDbCloseConnections();
678 // Deletion of the wxDbConnectInf instance must be the LAST thing done that
679 // has anything to do with the database. Deleting this before disconnecting,
680 // freeing/closing connections, etc will result in a crash!
681 wxDELETE(wxGetApp().DbConnectInf
);
685 } // DatabaseDemoFrame::OnCloseWindow()
688 void DatabaseDemoFrame::BuildEditorDialog()
691 pEditorDlg
= new CeditorDlg(this);
694 pEditorDlg
->Initialize();
695 if (!pEditorDlg
->initialized
)
699 wxMessageBox(wxT("Unable to initialize the editor dialog for some reason"),wxT("Error..."),wxOK
| wxICON_EXCLAMATION
);
705 wxMessageBox(wxT("Unable to create the editor dialog for some reason"),wxT("Error..."),wxOK
| wxICON_EXCLAMATION
);
708 } // DatabaseDemoFrame::BuildEditorDialog()
711 void DatabaseDemoFrame::BuildParameterDialog(wxWindow
*parent
)
713 pParamDlg
= new CparameterDlg(parent
);
716 wxMessageBox(wxT("Unable to create the parameter dialog for some reason"),wxT("Error..."),wxOK
| wxICON_EXCLAMATION
);
717 } // DatabaseDemoFrame::BuildParameterDialog()
721 * Constructor note: If no wxDb object is passed in, a new connection to the database
722 * is created for this instance of Ccontact. This can be a slow process depending
723 * on the database engine being used, and some database engines have a limit on the
724 * number of connections (either hard limits, or license restricted) so care should
725 * be used to use as few connections as is necessary.
727 * IMPORTANT: Objects which share a wxDb pointer are ALL acted upon whenever a member
728 * function of pDb is called (i.e. CommitTrans() or RollbackTrans(), so if modifying
729 * or creating a table objects which use the same pDb, know that all the objects
730 * will be committed or rolled back when any of the objects has this function call made.
732 Ccontact::Ccontact (wxDb
*pwxDb
) : wxDbTable(pwxDb
? pwxDb
: wxDbGetConnection(wxGetApp().DbConnectInf
),
733 CONTACT_TABLE_NAME
, CONTACT_NO_COLS
, wxT(""),
734 !wxDB_QUERY_ONLY
, wxGetApp().DbConnectInf
->GetDefaultDir())
736 // This is used to represent whether the database connection should be released
737 // when this instance of the object is deleted. If using the same connection
738 // for multiple instance of database objects, then the connection should only be
739 // released when the last database instance using the connection is deleted
743 GetDb()->SetSqlLogging(sqlLogON
);
747 } // Ccontact Constructor
750 void Ccontact::Initialize()
759 JoinDate
.year
= 1980;
765 JoinDate
.fraction
= 0;
766 NativeLanguage
= langENGLISH
;
770 } // Ccontact::Initialize
773 Ccontact::~Ccontact()
777 if (!wxDbFreeConnection(GetDb()))
780 tStr
= wxT("Unable to Free the Ccontact data table handle\n\n");
781 tStr
+= GetExtendedDBErrorMsg(GetDb(),__FILE__
,__LINE__
);
782 wxMessageBox(tStr
,wxT("ODBC Error..."),wxOK
| wxICON_EXCLAMATION
);
785 } // Ccontract destructor
789 * Handles setting up all the connections for the interface from the wxDbTable
790 * functions to interface to the data structure used to store records in
791 * memory, and for all the column definitions that define the table structure
793 void Ccontact::SetupColumns()
795 // NOTE: Columns now are 8 character names, as that is all dBase can support. Longer
796 // names can be used for other database engines
797 SetColDefs ( 0,wxT("NAME"), DB_DATA_TYPE_VARCHAR
, Name
, SQL_C_CHAR
, sizeof(Name
), TRUE
, TRUE
); // Primary index
798 SetColDefs ( 1,wxT("ADDRESS1"), DB_DATA_TYPE_VARCHAR
, Addr1
, SQL_C_CHAR
, sizeof(Addr1
), FALSE
,TRUE
);
799 SetColDefs ( 2,wxT("ADDRESS2"), DB_DATA_TYPE_VARCHAR
, Addr2
, SQL_C_CHAR
, sizeof(Addr2
), FALSE
,TRUE
);
800 SetColDefs ( 3,wxT("CITY"), DB_DATA_TYPE_VARCHAR
, City
, SQL_C_CHAR
, sizeof(City
), FALSE
,TRUE
);
801 SetColDefs ( 4,wxT("STATE"), DB_DATA_TYPE_VARCHAR
, State
, SQL_C_CHAR
, sizeof(State
), FALSE
,TRUE
);
802 SetColDefs ( 5,wxT("POSTCODE"), DB_DATA_TYPE_VARCHAR
, PostalCode
, SQL_C_CHAR
, sizeof(PostalCode
), FALSE
,TRUE
);
803 SetColDefs ( 6,wxT("COUNTRY"), DB_DATA_TYPE_VARCHAR
, Country
, SQL_C_CHAR
, sizeof(Country
), FALSE
,TRUE
);
804 SetColDefs ( 7,wxT("JOINDATE"), DB_DATA_TYPE_DATE
, &JoinDate
, SQL_C_TIMESTAMP
, sizeof(JoinDate
), FALSE
,TRUE
);
805 SetColDefs ( 8,wxT("IS_DEV"), DB_DATA_TYPE_INTEGER
, &IsDeveloper
, SQL_C_BOOLEAN(IsDeveloper
), sizeof(IsDeveloper
), FALSE
,TRUE
);
806 SetColDefs ( 9,wxT("CONTRIBS"), DB_DATA_TYPE_INTEGER
, &Contributions
, SQL_C_USHORT
, sizeof(Contributions
), FALSE
,TRUE
);
807 SetColDefs (10,wxT("LINE_CNT"), DB_DATA_TYPE_INTEGER
, &LinesOfCode
, SQL_C_ULONG
, sizeof(LinesOfCode
), FALSE
,TRUE
);
808 SetColDefs (11,wxT("LANGUAGE"), DB_DATA_TYPE_INTEGER
, &NativeLanguage
, SQL_C_ENUM
, sizeof(NativeLanguage
), FALSE
,TRUE
);
809 #if wxODBC_BLOB_EXPERIMENT > 0
810 SetColDefs (12,wxT("PICTURE"), DB_DATA_TYPE_BLOB
, Picture
, SQL_LONGVARBINARY
, sizeof(Picture
), FALSE
,TRUE
);
812 } // Ccontact::SetupColumns
815 bool Ccontact::CreateIndexes(bool recreate
)
817 // This index could easily be accomplished with an "orderBy" clause,
818 // but is done to show how to construct a non-primary index.
820 wxDbIdxDef idxDef
[2];
824 wxStrcpy(idxDef
[0].ColName
, "IS_DEV");
825 idxDef
[0].Ascending
= TRUE
;
827 wxStrcpy(idxDef
[1].ColName
, "NAME");
828 idxDef
[1].Ascending
= TRUE
;
830 indexName
= GetTableName();
831 indexName
+= "_IDX1";
832 Ok
= CreateIndex(indexName
.c_str(), TRUE
, 2, idxDef
, recreate
);
835 } // Ccontact::CreateIndexes()
839 * Having a function to do a query on the primary key (and possibly others) is
840 * very efficient and tighter coding so that it is available where ever the object
841 * is. Great for use with multiple tables when not using views or outer joins
843 bool Ccontact::FetchByName(const wxString
&name
)
845 whereStr
.Printf(wxT("NAME = '%s'"),name
.c_str());
846 SetWhereClause(whereStr
.c_str());
847 SetOrderByClause(wxT(""));
855 } // Ccontact::FetchByName()
860 * ************* DIALOGS ***************
865 /* CeditorDlg constructor
867 * Creates the dialog used for creating/editing/deleting/copying a Ccontact object.
868 * This dialog actually is drawn in the main frame of the program
870 * An instance of Ccontact is created - "Contact" - which is used to hold the Ccontact
871 * object that is currently being worked with.
874 BEGIN_EVENT_TABLE(CeditorDlg
, wxPanel
)
875 EVT_BUTTON(-1, CeditorDlg::OnButton
)
876 EVT_CLOSE(CeditorDlg::OnCloseWindow
)
879 CeditorDlg::CeditorDlg(wxWindow
*parent
) : wxPanel (parent
, 0, 0, 537, 480)
881 // Since the ::OnCommand() function is overridden, this prevents the widget
882 // detection in ::OnCommand() until all widgets have been initialized to prevent
883 // uninitialized pointers from crashing the program
884 widgetPtrsSet
= FALSE
;
891 } // CeditorDlg constructor
894 void CeditorDlg::OnCloseWindow(wxCloseEvent
& event
)
897 if ((mode
!= mCreate
) && (mode
!= mEdit
))
903 wxMessageBox(wxT("Must finish processing the current record being created/modified before exiting"),wxT("Notice..."),wxOK
| wxICON_INFORMATION
);
906 } // CeditorDlg::OnCloseWindow()
909 void CeditorDlg::OnButton(wxCommandEvent
&event
)
911 wxWindow
*win
= (wxWindow
*) event
.GetEventObject();
912 OnCommand( *win
, event
);
913 } // CeditorDlg::OnButton()
916 void CeditorDlg::OnCommand(wxWindow
& win
, wxCommandEvent
& event
)
920 widgetName
= win
.GetName();
925 if (widgetName
== pCreateBtn
->GetName())
927 wxGetApp().Contact
->Initialize();
930 pNameTxt
->SetValue(wxT(""));
931 pNameTxt
->SetFocus();
935 if (widgetName
== pEditBtn
->GetName())
937 saveName
= wxGetApp().Contact
->Name
;
939 pNameTxt
->SetFocus();
943 if (widgetName
== pCopyBtn
->GetName())
946 pNameTxt
->SetValue(wxT(""));
947 pNameTxt
->SetFocus();
951 if (widgetName
== pDeleteBtn
->GetName())
953 bool Ok
= (wxMessageBox(wxT("Are you sure?"),wxT("Confirm"),wxYES_NO
|wxICON_QUESTION
) == wxYES
);
958 if (Ok
&& wxGetApp().Contact
->Delete())
960 // NOTE: Deletions are not finalized until a CommitTrans() is performed.
961 // If the commit were not performed, the program will continue to
962 // show the table contents as if they were deleted until this instance
963 // of Ccontact is deleted. If the Commit wasn't performed, the
964 // database will automatically Rollback the changes when the database
965 // connection is terminated
966 wxGetApp().Contact
->GetDb()->CommitTrans();
968 // Try to get the row that followed the just deleted row in the orderBy sequence
971 // There was now row (in sequence) after the just deleted row, so get the
972 // row which preceded the just deleted row
975 // There are now no rows remaining, so clear the dialog widgets
976 wxGetApp().Contact
->Initialize();
980 SetMode(mode
); // force reset of button enable/disable
984 wxGetApp().Contact
->GetDb()->RollbackTrans();
990 if (widgetName
== pSaveBtn
->GetName())
996 if (widgetName
== pCancelBtn
->GetName())
998 bool Ok
= (wxMessageBox(wxT("Are you sure?"),wxT("Confirm"),wxYES_NO
|wxICON_QUESTION
) == wxYES
);
1003 if (saveName
.IsEmpty())
1005 wxGetApp().Contact
->Initialize();
1012 // Requery previous record
1013 if (wxGetApp().Contact
->FetchByName(saveName
))
1021 // Previous record not available, retrieve first record in table
1022 if (wxGetApp().Contact
->GetDb()->Dbms() != dbmsPOSTGRES
&&
1023 wxGetApp().Contact
->GetDb()->Dbms() != dbmsMY_SQL
)
1025 wxGetApp().Contact
->whereStr
= wxT("NAME = (SELECT MIN(NAME) FROM ");
1026 wxGetApp().Contact
->whereStr
+= wxGetApp().Contact
->GetTableName();
1027 wxGetApp().Contact
->whereStr
+= wxT(")");
1028 wxGetApp().Contact
->SetWhereClause(wxGetApp().Contact
->whereStr
.c_str());
1031 wxGetApp().Contact
->SetWhereClause(wxT(""));
1033 if (!wxGetApp().Contact
->Query())
1036 tStr
= wxT("ODBC error during Query()\n\n");
1037 tStr
+= GetExtendedDBErrorMsg(wxGetApp().Contact
->GetDb(),__FILE__
,__LINE__
);
1038 wxMessageBox(tStr
,wxT("ODBC Error..."),wxOK
| wxICON_EXCLAMATION
);
1042 if (wxGetApp().Contact
->GetNext()) // Successfully read first record
1048 // No contacts are available, clear dialog
1049 wxGetApp().Contact
->Initialize();
1055 if (widgetName
== pPrevBtn
->GetName())
1062 if (widgetName
== pNextBtn
->GetName())
1069 if (widgetName
== pQueryBtn
->GetName())
1071 // Display the query dialog box
1072 wxChar qryWhere
[DB_MAX_WHERE_CLAUSE_LEN
+1];
1073 wxStrcpy(qryWhere
, (const wxChar
*) wxGetApp().Contact
->qryWhereStr
);
1074 wxChar
*tblName
[] = {(wxChar
*)CONTACT_TABLE_NAME
, 0};
1075 new CqueryDlg(GetParent(), wxGetApp().Contact
->GetDb(), tblName
, qryWhere
);
1077 // Query the first record in the new record set and
1078 // display it, if the query string has changed.
1079 if (wxStrcmp(qryWhere
, (const wxChar
*) wxGetApp().Contact
->qryWhereStr
))
1081 wxGetApp().Contact
->whereStr
.Empty();
1082 wxGetApp().Contact
->SetOrderByClause("NAME");
1084 if (wxGetApp().Contact
->GetDb()->Dbms() != dbmsPOSTGRES
&&
1085 wxGetApp().Contact
->GetDb()->Dbms() != dbmsMY_SQL
)
1087 wxGetApp().Contact
->whereStr
= wxT("NAME = (SELECT MIN(NAME) FROM ");
1088 wxGetApp().Contact
->whereStr
+= CONTACT_TABLE_NAME
;
1091 // Append the query where string (if there is one)
1092 wxGetApp().Contact
->qryWhereStr
= qryWhere
;
1093 if (wxStrlen(qryWhere
))
1095 wxGetApp().Contact
->whereStr
+= wxT(" WHERE ");
1096 wxGetApp().Contact
->whereStr
+= wxGetApp().Contact
->qryWhereStr
;
1098 // Close the expression with a right paren
1099 wxGetApp().Contact
->whereStr
+= wxT(")");
1100 // Requery the table
1101 wxGetApp().Contact
->SetWhereClause(wxGetApp().Contact
->whereStr
.c_str());
1102 if (!wxGetApp().Contact
->Query())
1105 tStr
= wxT("ODBC error during Query()\n\n");
1106 tStr
+= GetExtendedDBErrorMsg(wxGetApp().Contact
->GetDb(),__FILE__
,__LINE__
);
1107 wxMessageBox(tStr
,wxT("ODBC Error..."),wxOK
| wxICON_EXCLAMATION
);
1110 // Display the first record from the query set
1111 if (!wxGetApp().Contact
->GetNext())
1112 wxGetApp().Contact
->Initialize();
1116 // Enable/Disable the reset button
1117 pResetBtn
->Enable(!wxGetApp().Contact
->qryWhereStr
.IsEmpty());
1123 if (widgetName
== pResetBtn
->GetName())
1125 // Clear the additional where criteria established by the query feature
1126 wxGetApp().Contact
->qryWhereStr
= wxT("");
1127 wxGetApp().Contact
->SetOrderByClause(wxT("NAME"));
1129 if (wxGetApp().Contact
->GetDb()->Dbms() != dbmsPOSTGRES
&&
1130 wxGetApp().Contact
->GetDb()->Dbms() != dbmsMY_SQL
)
1132 wxGetApp().Contact
->whereStr
= wxT("NAME = (SELECT MIN(NAME) FROM ");
1133 wxGetApp().Contact
->whereStr
+= CONTACT_TABLE_NAME
;
1134 wxGetApp().Contact
->whereStr
+= wxT(")");
1137 wxGetApp().Contact
->SetWhereClause(wxGetApp().Contact
->whereStr
.c_str());
1138 if (!wxGetApp().Contact
->Query())
1141 tStr
= wxT("ODBC error during Query()\n\n");
1142 tStr
+= GetExtendedDBErrorMsg(wxGetApp().Contact
->GetDb(),__FILE__
,__LINE__
);
1143 wxMessageBox(tStr
,wxT("ODBC Error..."),wxOK
| wxICON_EXCLAMATION
);
1146 if (!wxGetApp().Contact
->GetNext())
1147 wxGetApp().Contact
->Initialize();
1149 pResetBtn
->Enable(FALSE
);
1155 if (widgetName
== pNameListBtn
->GetName())
1157 new ClookUpDlg(/* wxWindow *parent */ this,
1158 /* wxChar *windowTitle */ wxT("Select contact name"),
1159 /* wxChar *tableName */ (wxChar
*) CONTACT_TABLE_NAME
,
1160 /* wxChar *dispCol1 */ wxT("NAME"),
1161 /* wxChar *dispCol2 */ wxT("JOINDATE"),
1162 /* wxChar *where */ wxT(""),
1163 /* wxChar *orderBy */ wxT("NAME"),
1164 /* wxDb *pDb */ wxGetApp().READONLY_DB
,
1165 /* const wxString &defDir */ wxGetApp().DbConnectInf
->GetDefaultDir(),
1166 /* bool distinctValues */ TRUE
);
1168 if (ListDB_Selection
&& wxStrlen(ListDB_Selection
))
1170 wxString w
= wxT("NAME = '");
1171 w
+= ListDB_Selection
;
1179 if (widgetName
== pDataTypesBtn
->GetName())
1181 CheckSupportForAllDataTypes(wxGetApp().READONLY_DB
);
1182 wxMessageBox("Support datatypes was dumped to stdout.");
1184 } // Data types Button
1186 if (widgetName
== pDbDiagsBtn
->GetName())
1188 DisplayDbDiagnostics(wxGetApp().READONLY_DB
);
1189 wxMessageBox("Diagnostics info was dumped to stdout.");
1193 if (widgetName
== pCatalogBtn
->GetName())
1195 if (wxGetApp().Contact
->GetDb()->Catalog("","catalog.txt"))
1196 wxMessageBox("The file 'catalog.txt' was created.");
1198 wxMessageBox("Creation of the file 'catalog.txt' was failed.");
1202 } // CeditorDlg::OnCommand()
1205 bool CeditorDlg::Initialize()
1207 // Create the data structure and a new database connection.
1208 // (As there is not a pDb being passed in the constructor, a new database
1209 // connection is created)
1210 wxGetApp().Contact
= new Ccontact();
1212 if (!wxGetApp().Contact
)
1214 wxMessageBox(wxT("Unable to instantiate an instance of Ccontact"),wxT("Error..."),wxOK
| wxICON_EXCLAMATION
);
1218 // Check if the table exists or not. If it doesn't, ask the user if they want to
1219 // create the table. Continue trying to create the table until it exists, or user aborts
1220 while (!wxGetApp().Contact
->GetDb()->TableExists((wxChar
*)CONTACT_TABLE_NAME
,
1221 wxGetApp().DbConnectInf
->GetUserID(),
1222 wxGetApp().DbConnectInf
->GetDefaultDir()))
1225 tStr
.Printf(wxT("Unable to open the table '%s'.\n\nTable may need to be created...?\n\n"),CONTACT_TABLE_NAME
);
1226 tStr
+= GetExtendedDBErrorMsg(wxGetApp().Contact
->GetDb(),__FILE__
,__LINE__
);
1227 wxMessageBox(tStr
,wxT("ODBC Error..."),wxOK
| wxICON_EXCLAMATION
);
1229 bool createTable
= (wxMessageBox(wxT("Do you wish to try to create/clear the CONTACTS table?"),wxT("Confirm"),wxYES_NO
|wxICON_QUESTION
) == wxYES
);
1237 wxGetApp().CreateDataTable(FALSE
);
1240 // Tables must be "opened" before anything other than creating/deleting table can be done
1241 if (!wxGetApp().Contact
->Open())
1243 // Table does exist, or there was some problem opening it. Currently this should
1244 // never fail, except in the case of the table not exisiting or the current
1245 // user has insufficent privileges to access the table
1247 // This code is experimenting with a new function that will hopefully be available
1248 // in the 2.4 release. This check will determine whether the open failing was due
1249 // to the table not existing, or the users privileges being insufficient to
1251 if (!wxGetApp().Contact
->GetDb()->TablePrivileges(CONTACT_TABLE_NAME
, wxT("SELECT"),
1252 wxGetApp().Contact
->GetDb()->GetUsername(),
1253 wxGetApp().Contact
->GetDb()->GetUsername(),
1254 wxGetApp().DbConnectInf
->GetDefaultDir()))
1257 tStr
.Printf(wxT("Unable to open the table '%s' (likely due to\ninsufficient privileges of the logged in user).\n\n"),CONTACT_TABLE_NAME
);
1258 tStr
+= GetExtendedDBErrorMsg(wxGetApp().Contact
->GetDb(),__FILE__
,__LINE__
);
1259 wxMessageBox(tStr
,wxT("ODBC Error..."),wxOK
| wxICON_EXCLAMATION
);
1263 if (!wxGetApp().Contact
->GetDb()->TableExists(CONTACT_TABLE_NAME
,
1264 wxGetApp().Contact
->GetDb()->GetUsername(),
1265 wxGetApp().DbConnectInf
->GetDefaultDir()))
1268 tStr
.Printf(wxT("Unable to open the table '%s' as the table\ndoes not appear to exist in the tablespace available\nto the currently logged in user.\n\n"),CONTACT_TABLE_NAME
);
1269 tStr
+= GetExtendedDBErrorMsg(wxGetApp().Contact
->GetDb(),__FILE__
,__LINE__
);
1270 wxMessageBox(tStr
,wxT("ODBC Error..."),wxOK
| wxICON_EXCLAMATION
);
1278 (void)new wxStaticBox(this, EDITOR_DIALOG_FN_GROUP
, wxT(""), wxPoint(15, 1), wxSize(497, 69), 0, wxT("FunctionGrp"));
1279 (void)new wxStaticBox(this, EDITOR_DIALOG_SEARCH_GROUP
, wxT(""), wxPoint(417, 1), wxSize(95, 242), 0, wxT("SearchGrp"));
1281 pCreateBtn
= new wxButton(this, EDITOR_DIALOG_CREATE
, wxT("&Create"), wxPoint( 25, 21), wxSize( 70, 35), 0, wxDefaultValidator
, wxT("CreateBtn"));
1282 pEditBtn
= new wxButton(this, EDITOR_DIALOG_EDIT
, wxT("&Edit"), wxPoint(102, 21), wxSize( 70, 35), 0, wxDefaultValidator
, wxT("EditBtn"));
1283 pDeleteBtn
= new wxButton(this, EDITOR_DIALOG_DELETE
, wxT("&Delete"), wxPoint(179, 21), wxSize( 70, 35), 0, wxDefaultValidator
, wxT("DeleteBtn"));
1284 pCopyBtn
= new wxButton(this, EDITOR_DIALOG_COPY
, wxT("Cop&y"), wxPoint(256, 21), wxSize( 70, 35), 0, wxDefaultValidator
, wxT("CopyBtn"));
1285 pSaveBtn
= new wxButton(this, EDITOR_DIALOG_SAVE
, wxT("&Save"), wxPoint(333, 21), wxSize( 70, 35), 0, wxDefaultValidator
, wxT("SaveBtn"));
1286 pCancelBtn
= new wxButton(this, EDITOR_DIALOG_CANCEL
, wxT("C&ancel"), wxPoint(430, 21), wxSize( 70, 35), 0, wxDefaultValidator
, wxT("CancelBtn"));
1287 pPrevBtn
= new wxButton(this, EDITOR_DIALOG_PREV
, wxT("<< &Prev"), wxPoint(430, 81), wxSize( 70, 35), 0, wxDefaultValidator
, wxT("PrevBtn"));
1288 pNextBtn
= new wxButton(this, EDITOR_DIALOG_NEXT
, wxT("&Next >>"), wxPoint(430, 121), wxSize( 70, 35), 0, wxDefaultValidator
, wxT("NextBtn"));
1289 pQueryBtn
= new wxButton(this, EDITOR_DIALOG_QUERY
, wxT("&Query"), wxPoint(430, 161), wxSize( 70, 35), 0, wxDefaultValidator
, wxT("QueryBtn"));
1290 pResetBtn
= new wxButton(this, EDITOR_DIALOG_RESET
, wxT("&Reset"), wxPoint(430, 200), wxSize( 70, 35), 0, wxDefaultValidator
, wxT("ResetBtn"));
1291 pNameMsg
= new wxStaticText(this, EDITOR_DIALOG_NAME_MSG
, wxT("Name:"), wxPoint( 17, 80), wxSize( -1, -1), 0, wxT("NameMsg"));
1292 pNameTxt
= new wxTextCtrl(this, EDITOR_DIALOG_NAME_TEXT
, wxT(""), wxPoint( 17, 97), wxSize(308, 25), 0, wxDefaultValidator
, wxT("NameTxt"));
1293 pNameListBtn
= new wxButton(this, EDITOR_DIALOG_LOOKUP
, wxT("&Lookup"), wxPoint(333, 97), wxSize( 70, 24), 0, wxDefaultValidator
, wxT("LookupBtn"));
1294 pAddress1Msg
= new wxStaticText(this, EDITOR_DIALOG_ADDRESS1_MSG
, wxT("Address:"), wxPoint( 17, 130), wxSize( -1, -1), 0, wxT("Address1Msg"));
1295 pAddress1Txt
= new wxTextCtrl(this, EDITOR_DIALOG_ADDRESS2_TEXT
, wxT(""), wxPoint( 17, 147), wxSize(308, 25), 0, wxDefaultValidator
, wxT("Address1Txt"));
1296 pAddress2Msg
= new wxStaticText(this, EDITOR_DIALOG_ADDRESS2_MSG
, wxT("Address:"), wxPoint( 17, 180), wxSize( -1, -1), 0, wxT("Address2Msg"));
1297 pAddress2Txt
= new wxTextCtrl(this, EDITOR_DIALOG_ADDRESS2_TEXT
, wxT(""), wxPoint( 17, 197), wxSize(308, 25), 0, wxDefaultValidator
, wxT("Address2Txt"));
1298 pCityMsg
= new wxStaticText(this, EDITOR_DIALOG_CITY_MSG
, wxT("City:"), wxPoint( 17, 230), wxSize( -1, -1), 0, wxT("CityMsg"));
1299 pCityTxt
= new wxTextCtrl(this, EDITOR_DIALOG_CITY_TEXT
, wxT(""), wxPoint( 17, 247), wxSize(225, 25), 0, wxDefaultValidator
, wxT("CityTxt"));
1300 pStateMsg
= new wxStaticText(this, EDITOR_DIALOG_STATE_MSG
, wxT("State:"), wxPoint(250, 230), wxSize( -1, -1), 0, wxT("StateMsg"));
1301 pStateTxt
= new wxTextCtrl(this, EDITOR_DIALOG_STATE_TEXT
, wxT(""), wxPoint(250, 247), wxSize(153, 25), 0, wxDefaultValidator
, wxT("StateTxt"));
1302 pCountryMsg
= new wxStaticText(this, EDITOR_DIALOG_COUNTRY_MSG
, wxT("Country:"), wxPoint( 17, 280), wxSize( -1, -1), 0, wxT("CountryMsg"));
1303 pCountryTxt
= new wxTextCtrl(this, EDITOR_DIALOG_COUNTRY_TEXT
, wxT(""), wxPoint( 17, 297), wxSize(225, 25), 0, wxDefaultValidator
, wxT("CountryTxt"));
1304 pPostalCodeMsg
= new wxStaticText(this, EDITOR_DIALOG_POSTAL_MSG
, wxT("Postal Code:"),wxPoint(250, 280), wxSize( -1, -1), 0, wxT("PostalCodeMsg"));
1305 pPostalCodeTxt
= new wxTextCtrl(this, EDITOR_DIALOG_POSTAL_TEXT
, wxT(""), wxPoint(250, 297), wxSize(153, 25), 0, wxDefaultValidator
, wxT("PostalCodeTxt"));
1307 wxString choice_strings
[5];
1308 choice_strings
[0] = wxT("English");
1309 choice_strings
[1] = wxT("French");
1310 choice_strings
[2] = wxT("German");
1311 choice_strings
[3] = wxT("Spanish");
1312 choice_strings
[4] = wxT("Other");
1314 pNativeLangChoice
= new wxChoice(this, EDITOR_DIALOG_LANG_CHOICE
, wxPoint( 17, 346), wxSize(277, -1), 5, choice_strings
);
1315 pNativeLangMsg
= new wxStaticText(this, EDITOR_DIALOG_LANG_MSG
, wxT("Native language:"), wxPoint( 17, 330), wxSize( -1, -1), 0, wxT("NativeLangMsg"));
1317 wxString radio_strings
[2];
1318 radio_strings
[0] = wxT("No");
1319 radio_strings
[1] = wxT("Yes");
1320 pDeveloperRadio
= new wxRadioBox(this,EDITOR_DIALOG_DEVELOPER
, wxT("Developer:"), wxPoint(303, 330), wxSize( -1, -1), 2, radio_strings
, 2, wxHORIZONTAL
);
1321 pJoinDateMsg
= new wxStaticText(this, EDITOR_DIALOG_JOIN_MSG
, wxT("Date joined:"), wxPoint( 17, 380), wxSize( -1, -1), 0, wxT("JoinDateMsg"));
1322 pJoinDateTxt
= new wxTextCtrl(this, EDITOR_DIALOG_JOIN_TEXT
, wxT(""), wxPoint( 17, 397), wxSize(150, 25), 0, wxDefaultValidator
, wxT("JoinDateTxt"));
1323 pContribMsg
= new wxStaticText(this, EDITOR_DIALOG_CONTRIB_MSG
,wxT("Contributions:"), wxPoint(175, 380), wxSize( -1, -1), 0, wxT("ContribMsg"));
1324 pContribTxt
= new wxTextCtrl(this, EDITOR_DIALOG_CONTRIB_TEXT
, wxT(""), wxPoint(175, 397), wxSize(120, 25), 0, wxDefaultValidator
, wxT("ContribTxt"));
1325 pLinesMsg
= new wxStaticText(this, EDITOR_DIALOG_LINES_MSG
, wxT("Lines of code:"), wxPoint(303, 380), wxSize( -1, -1), 0, wxT("LinesMsg"));
1326 pLinesTxt
= new wxTextCtrl(this, EDITOR_DIALOG_LINES_TEXT
, wxT(""), wxPoint(303, 397), wxSize(100, 25), 0, wxDefaultValidator
, wxT("LinesTxt"));
1328 pCatalogBtn
= new wxButton(this, EDITOR_DIALOG_CATALOG
, wxT("Catalo&g"), wxPoint(430, 287), wxSize( 70, 35), 0, wxDefaultValidator
, wxT("CatalogBtn"));
1329 pDataTypesBtn
= new wxButton(this, EDITOR_DIALOG_DATATYPES
, wxT("Data&types"), wxPoint(430, 337), wxSize( 70, 35), 0, wxDefaultValidator
, wxT("DataTypesBtn"));
1330 pDbDiagsBtn
= new wxButton(this, EDITOR_DIALOG_DB_DIAGS
, wxT("DB Dia&gs"), wxPoint(430, 387), wxSize( 70, 35), 0, wxDefaultValidator
, wxT("DbDiagsBtn"));
1332 // Now that all the widgets on the panel are created, its safe to allow ::OnCommand() to
1333 // handle all widget processing
1334 widgetPtrsSet
= TRUE
;
1336 // Setup the orderBy and where clauses to return back a single record as the result set,
1337 // as there will only be one record being shown on the dialog at a time, this optimizes
1338 // network traffic by only returning a one row result
1340 wxGetApp().Contact
->SetOrderByClause(wxT("NAME")); // field name to sort by
1342 // The wxString "whereStr" is not a member of the wxDbTable object, it is a member variable
1343 // specifically in the Ccontact class. It is used here for simpler construction of a varying
1344 // length string, and then after the string is built, the wxDbTable member variable "where" is
1345 // assigned the pointer to the constructed string.
1347 // The constructed where clause below has a sub-query within it "SELECT MIN(NAME) FROM %s"
1348 // to achieve a single row (in this case the first name in alphabetical order).
1350 if (wxGetApp().Contact
->GetDb()->Dbms() != dbmsPOSTGRES
&&
1351 wxGetApp().Contact
->GetDb()->Dbms() != dbmsMY_SQL
)
1353 wxGetApp().Contact
->whereStr
.Printf(wxT("NAME = (SELECT MIN(NAME) FROM %s)"),
1354 wxGetApp().Contact
->GetTableName().c_str());
1355 // NOTE: (const wxChar*) returns a pointer which may not be valid later, so this is short term use only
1356 wxGetApp().Contact
->SetWhereClause(wxGetApp().Contact
->whereStr
);
1359 wxGetApp().Contact
->SetWhereClause(wxT(""));
1361 // Perform the Query to get the result set.
1362 // NOTE: If there are no rows returned, that is a valid result, so Query() would return TRUE.
1363 // Only if there is a database error will Query() come back as FALSE
1364 if (!wxGetApp().Contact
->Query())
1367 tStr
= wxT("ODBC error during Query()\n\n");
1368 tStr
+= GetExtendedDBErrorMsg(wxGetApp().Contact
->GetDb(),__FILE__
,__LINE__
);
1369 wxMessageBox(tStr
,wxT("ODBC Error..."),wxOK
| wxICON_EXCLAMATION
);
1373 // Since Query succeeded, now get the row that was returned
1374 if (!wxGetApp().Contact
->GetNext())
1375 // If the GetNext() failed at this point, then there are no rows to retrieve,
1376 // so clear the values in the members of "Contact" so that PutData() blanks the
1377 // widgets on the dialog
1378 wxGetApp().Contact
->Initialize();
1380 wxGetApp().Contact->GetDb()->RollbackTrans();
1389 } // CeditorDlg::Initialize()
1392 void CeditorDlg::FieldsEditable()
1397 pNameTxt
->Enable((mode
== mCreate
) || (mode
== mEdit
));
1398 pAddress1Txt
->Enable((mode
== mCreate
) || (mode
== mEdit
));
1399 pAddress2Txt
->Enable((mode
== mCreate
) || (mode
== mEdit
));
1400 pCityTxt
->Enable((mode
== mCreate
) || (mode
== mEdit
));
1401 pStateTxt
->Enable((mode
== mCreate
) || (mode
== mEdit
));
1402 pPostalCodeTxt
->Enable((mode
== mCreate
) || (mode
== mEdit
));
1403 pCountryTxt
->Enable((mode
== mCreate
) || (mode
== mEdit
));
1405 pJoinDateTxt
->Enable((mode
== mCreate
) || (mode
== mEdit
));
1406 pContribTxt
->Enable((mode
== mCreate
) || (mode
== mEdit
));
1407 pLinesTxt
->Enable((mode
== mCreate
) || (mode
== mEdit
));
1408 pNativeLangChoice
->Enable((mode
== mCreate
) || (mode
== mEdit
));
1409 pDeveloperRadio
->Enable((mode
== mCreate
) || (mode
== mEdit
));
1411 } // CeditorDlg::FieldsEditable()
1414 void CeditorDlg::SetMode(enum DialogModes m
)
1435 pCreateBtn
->Enable( !edit
);
1436 pEditBtn
->Enable( !edit
&& (wxStrcmp(wxGetApp().Contact
->Name
,wxT(""))!=0) );
1437 pDeleteBtn
->Enable( !edit
&& (wxStrcmp(wxGetApp().Contact
->Name
,wxT(""))!=0) );
1438 pCopyBtn
->Enable( !edit
&& (wxStrcmp(wxGetApp().Contact
->Name
,wxT(""))!=0) );
1439 pSaveBtn
->Enable( edit
);
1440 pCancelBtn
->Enable( edit
);
1441 pPrevBtn
->Enable( !edit
);
1442 pNextBtn
->Enable( !edit
);
1443 pQueryBtn
->Enable( !edit
);
1444 pResetBtn
->Enable( !edit
&& !wxGetApp().Contact
->qryWhereStr
.IsEmpty() );
1445 pNameListBtn
->Enable( !edit
);
1449 } // CeditorDlg::SetMode()
1452 bool CeditorDlg::PutData()
1456 pNameTxt
->SetValue(wxGetApp().Contact
->Name
);
1457 pAddress1Txt
->SetValue(wxGetApp().Contact
->Addr1
);
1458 pAddress2Txt
->SetValue(wxGetApp().Contact
->Addr2
);
1459 pCityTxt
->SetValue(wxGetApp().Contact
->City
);
1460 pStateTxt
->SetValue(wxGetApp().Contact
->State
);
1461 pCountryTxt
->SetValue(wxGetApp().Contact
->Country
);
1462 pPostalCodeTxt
->SetValue(wxGetApp().Contact
->PostalCode
);
1464 tStr
.Printf(wxT("%d/%d/%d"),wxGetApp().Contact
->JoinDate
.month
,wxGetApp().Contact
->JoinDate
.day
,wxGetApp().Contact
->JoinDate
.year
);
1465 pJoinDateTxt
->SetValue(tStr
);
1467 tStr
.Printf(wxT("%d"),wxGetApp().Contact
->Contributions
);
1468 pContribTxt
->SetValue(tStr
);
1470 tStr
.Printf(wxT("%lu"),wxGetApp().Contact
->LinesOfCode
);
1471 pLinesTxt
->SetValue(tStr
);
1473 pNativeLangChoice
->SetSelection(wxGetApp().Contact
->NativeLanguage
);
1475 pDeveloperRadio
->SetSelection(wxGetApp().Contact
->IsDeveloper
);
1478 } // Ceditor::PutData()
1482 * Reads the data out of all the widgets on the dialog. Some data evaluation is done
1483 * to ensure that there is a name entered and that the date field is valid.
1485 * A return value of TRUE means that valid data was retrieved from the dialog, otherwise
1486 * invalid data was found (and a message was displayed telling the user what to fix), and
1487 * the data was not placed into the appropraite fields of Ccontact
1489 bool CeditorDlg::GetData()
1491 // Validate that the data currently entered into the widgets is valid data
1494 tStr
= pNameTxt
->GetValue();
1495 if (!wxStrcmp((const wxChar
*) tStr
,wxT("")))
1497 wxMessageBox(wxT("A name is required for entry into the contact table"),wxT("Notice..."),wxOK
| wxICON_INFORMATION
);
1501 bool invalid
= FALSE
;
1505 tStr
= pJoinDateTxt
->GetValue();
1506 if (tStr
.Freq(wxT('/')) != 2)
1509 // Find the month, day, and year tokens
1512 first
= tStr
.First(wxT('/'));
1513 second
= tStr
.Last(wxT('/'));
1515 mm
= atoi(tStr
.SubString(0,first
));
1516 dd
= atoi(tStr
.SubString(first
+1,second
));
1517 yyyy
= atoi(tStr
.SubString(second
+1,tStr
.Length()-1));
1519 invalid
= !(mm
&& dd
&& yyyy
);
1522 // Force Year 2000 compliance
1523 if (!invalid
&& (yyyy
< 1000))
1526 // Check the token ranges for validity
1531 else if ((mm
< 1) || (mm
> 12))
1539 int days
[12] = {31,28,31,30,31,30,
1541 if (dd
> days
[mm
-1])
1544 if ((dd
== 29) && (mm
== 2))
1546 if (((yyyy
% 4) == 0) && (((yyyy
% 100) != 0) || ((yyyy
% 400) == 0)))
1556 wxGetApp().Contact
->JoinDate
.month
= mm
;
1557 wxGetApp().Contact
->JoinDate
.day
= dd
;
1558 wxGetApp().Contact
->JoinDate
.year
= yyyy
;
1562 wxMessageBox(wxT("Improper date format. Please check the date\nspecified and try again.\n\nNOTE: Dates are in american format (MM/DD/YYYY)"),wxT("Notice..."),wxOK
| wxICON_INFORMATION
);
1566 tStr
= pNameTxt
->GetValue();
1567 wxStrcpy(wxGetApp().Contact
->Name
,(const wxChar
*) tStr
);
1568 wxStrcpy(wxGetApp().Contact
->Addr1
,pAddress1Txt
->GetValue());
1569 wxStrcpy(wxGetApp().Contact
->Addr2
,pAddress2Txt
->GetValue());
1570 wxStrcpy(wxGetApp().Contact
->City
,pCityTxt
->GetValue());
1571 wxStrcpy(wxGetApp().Contact
->State
,pStateTxt
->GetValue());
1572 wxStrcpy(wxGetApp().Contact
->Country
,pCountryTxt
->GetValue());
1573 wxStrcpy(wxGetApp().Contact
->PostalCode
,pPostalCodeTxt
->GetValue());
1575 wxGetApp().Contact
->Contributions
= atoi(pContribTxt
->GetValue());
1576 wxGetApp().Contact
->LinesOfCode
= atol(pLinesTxt
->GetValue());
1578 wxGetApp().Contact
->NativeLanguage
= (enum Language
) pNativeLangChoice
->GetSelection();
1579 wxGetApp().Contact
->IsDeveloper
= pDeveloperRadio
->GetSelection() > 0;
1582 } // CeditorDlg::GetData()
1586 * Retrieve data from the dialog, verify the validity of the data, and if it is valid,
1587 * try to insert/update the data to the table based on the current 'mode' the dialog
1590 * A return value of TRUE means the insert/update was completed successfully, a return
1591 * value of FALSE means that Save() failed. If returning FALSE, then this function
1592 * has displayed a detailed error message for the user.
1594 bool CeditorDlg::Save()
1596 bool failed
= FALSE
;
1598 // Read the data in the widgets of the dialog to get the user's data
1602 // Perform any other required validations necessary before saving
1605 wxBeginBusyCursor();
1607 if (mode
== mCreate
)
1609 RETCODE result
= wxGetApp().Contact
->Insert();
1611 failed
= (result
!= DB_SUCCESS
);
1614 // Some errors may be expected, like a duplicate key, so handle those instances with
1615 // specific error messages.
1616 if (result
== DB_ERR_INTEGRITY_CONSTRAINT_VIOL
)
1619 tStr
= wxT("A duplicate key value already exists in the table.\nUnable to save record\n\n");
1620 tStr
+= GetExtendedDBErrorMsg(wxGetApp().Contact
->GetDb(),__FILE__
,__LINE__
);
1621 wxMessageBox(tStr
,wxT("ODBC Error..."),wxOK
| wxICON_EXCLAMATION
);
1625 // Some other unexpected error occurred
1627 tStr
= wxT("Database insert failed\n\n");
1628 tStr
+= GetExtendedDBErrorMsg(wxGetApp().Contact
->GetDb(),__FILE__
,__LINE__
);
1629 wxMessageBox(tStr
,wxT("ODBC Error..."),wxOK
| wxICON_EXCLAMATION
);
1633 else // mode == mEdit
1635 wxGetApp().Contact
->GetDb()->RollbackTrans();
1636 wxGetApp().Contact
->whereStr
.Printf("NAME = '%s'",saveName
.c_str());
1637 if (!wxGetApp().Contact
->UpdateWhere(wxGetApp().Contact
->whereStr
))
1640 tStr
= wxT("Database update failed\n\n");
1641 tStr
+= GetExtendedDBErrorMsg(wxGetApp().Contact
->GetDb(),__FILE__
,__LINE__
);
1642 wxMessageBox(tStr
,wxT("ODBC Error..."),wxOK
| wxICON_EXCLAMATION
);
1649 wxGetApp().Contact
->GetDb()->CommitTrans();
1650 SetMode(mView
); // Sets the dialog mode back to viewing after save is successful
1653 wxGetApp().Contact
->GetDb()->RollbackTrans();
1659 } // CeditorDlg::Save()
1663 * Where this program is only showing a single row at a time in the dialog,
1664 * a special where clause must be built to find just the single row which,
1665 * in sequence, would follow the currently displayed row.
1667 bool CeditorDlg::GetNextRec()
1671 if (wxGetApp().Contact
->GetDb()->Dbms() != dbmsPOSTGRES
&&
1672 wxGetApp().Contact
->GetDb()->Dbms() != dbmsMY_SQL
)
1674 w
= wxT("NAME = (SELECT MIN(NAME) FROM ");
1675 w
+= wxGetApp().Contact
->GetTableName();
1676 w
+= wxT(" WHERE NAME > '");
1679 w
= wxT("(NAME > '");
1681 w
+= wxGetApp().Contact
->Name
;
1684 // If a query where string is currently set, append that criteria
1685 if (!wxGetApp().Contact
->qryWhereStr
.IsEmpty())
1688 w
+= wxGetApp().Contact
->qryWhereStr
;
1695 } // CeditorDlg::GetNextRec()
1699 * Where this program is only showing a single row at a time in the dialog,
1700 * a special where clause must be built to find just the single row which,
1701 * in sequence, would precede the currently displayed row.
1703 bool CeditorDlg::GetPrevRec()
1707 if (wxGetApp().Contact
->GetDb()->Dbms() != dbmsPOSTGRES
&&
1708 wxGetApp().Contact
->GetDb()->Dbms() != dbmsMY_SQL
)
1710 w
= wxT("NAME = (SELECT MAX(NAME) FROM ");
1711 w
+= wxGetApp().Contact
->GetTableName();
1712 w
+= wxT(" WHERE NAME < '");
1715 w
= wxT("(NAME < '");
1717 w
+= wxGetApp().Contact
->Name
;
1720 // If a query where string is currently set, append that criteria
1721 if (!wxGetApp().Contact
->qryWhereStr
.IsEmpty())
1724 w
+= wxGetApp().Contact
->qryWhereStr
;
1732 } // CeditorDlg::GetPrevRec()
1736 * This function is here to avoid duplicating this same code in both the
1737 * GetPrevRec() and GetNextRec() functions
1739 bool CeditorDlg::GetRec(const wxString
&whereStr
)
1741 wxGetApp().Contact
->SetWhereClause(whereStr
);
1742 wxGetApp().Contact
->SetOrderByClause(wxT("NAME"));
1744 if (!wxGetApp().Contact
->Query())
1747 tStr
= wxT("ODBC error during Query()\n\n");
1748 tStr
+= GetExtendedDBErrorMsg(wxGetApp().Contact
->GetDb(),__FILE__
,__LINE__
);
1749 wxMessageBox(tStr
,wxT("ODBC Error..."),wxOK
| wxICON_EXCLAMATION
);
1754 if (wxGetApp().Contact
->GetNext())
1761 } // CeditorDlg::GetRec()
1766 * CparameterDlg constructor
1769 BEGIN_EVENT_TABLE(CparameterDlg
, wxDialog
)
1770 EVT_BUTTON(PARAMETER_DIALOG_SAVE
, CparameterDlg::OnButton
)
1771 EVT_BUTTON(PARAMETER_DIALOG_CANCEL
, CparameterDlg::OnButton
)
1772 EVT_CLOSE(CparameterDlg::OnCloseWindow
)
1775 CparameterDlg::CparameterDlg(wxWindow
*parent
) : wxDialog (parent
, PARAMETER_DIALOG
, wxT("ODBC parameter settings"), wxPoint(-1, -1), wxSize(400, 325))
1777 // Since the ::OnCommand() function is overridden, this prevents the widget
1778 // detection in ::OnCommand() until all widgets have been initialized to prevent
1779 // uninitialized pointers from crashing the program
1780 widgetPtrsSet
= FALSE
;
1782 pParamODBCSourceMsg
= new wxStaticText(this, PARAMETER_DIALOG_SOURCE_MSG
, wxT("ODBC data sources:"), wxPoint( 10, 10), wxSize( -1, -1), 0, wxT("ParamODBCSourceMsg"));
1783 pParamODBCSourceList
= new wxListBox(this, PARAMETER_DIALOG_SOURCE_LISTBOX
, wxPoint( 10, 29), wxSize(285, 150), 0, 0, wxLB_SINGLE
|wxLB_ALWAYS_SB
, wxDefaultValidator
, wxT("ParamODBCSourceList"));
1784 pParamUserNameMsg
= new wxStaticText(this, PARAMETER_DIALOG_NAME_MSG
, wxT("Database user name:"), wxPoint( 10, 193), wxSize( -1, -1), 0, wxT("ParamUserNameMsg"));
1785 pParamUserNameTxt
= new wxTextCtrl(this, PARAMETER_DIALOG_NAME_TEXT
, wxT(""), wxPoint(10, 209), wxSize( 140, 25), 0, wxDefaultValidator
, wxT("ParamUserNameTxt"));
1786 pParamPasswordMsg
= new wxStaticText(this, PARAMETER_DIALOG_PASSWORD_MSG
, wxT("Password:"), wxPoint(156, 193), wxSize( -1, -1), 0, wxT("ParamPasswordMsg"));
1787 pParamPasswordTxt
= new wxTextCtrl(this, PARAMETER_DIALOG_PASSWORD_TEXT
, wxT(""), wxPoint(156, 209), wxSize( 140, 25), 0, wxDefaultValidator
, wxT("ParamPasswordTxt"));
1788 pParamDirPathMsg
= new wxStaticText(this, PARAMETER_DIALOG_DIRPATH_MSG
, wxT("Directory:"), wxPoint( 10, 243), wxSize( -1, -1), 0, wxT("ParamDirPathMsg"));
1789 pParamDirPathTxt
= new wxTextCtrl(this, PARAMETER_DIALOG_DIRPATH_TEXT
, wxT(""), wxPoint( 10, 259), wxSize(140, 25), 0, wxDefaultValidator
, wxT("ParamDirPathTxt"));
1790 pParamSaveBtn
= new wxButton(this, PARAMETER_DIALOG_SAVE
, wxT("&Save"), wxPoint(310, 21), wxSize( 70, 35), 0, wxDefaultValidator
, wxT("ParamSaveBtn"));
1791 pParamCancelBtn
= new wxButton(this, PARAMETER_DIALOG_CANCEL
, wxT("C&ancel"), wxPoint(310, 66), wxSize( 70, 35), 0, wxDefaultValidator
, wxT("ParamCancelBtn"));
1793 // Now that all the widgets on the panel are created, its safe to allow ::OnCommand() to
1794 // handle all widget processing
1795 widgetPtrsSet
= TRUE
;
1798 savedParamSettings
= wxGetApp().params
;
1803 } // CparameterDlg constructor
1806 void CparameterDlg::OnCloseWindow(wxCloseEvent
& event
)
1808 // Put any additional checking necessary to make certain it is alright
1809 // to close the program here that is not done elsewhere
1812 bool Ok
= (wxMessageBox(wxT("No changes have been saved.\n\nAre you sure you wish exit the parameter screen?"),wxT("Confirm"),wxYES_NO
|wxICON_QUESTION
) == wxYES
);
1820 wxGetApp().params
= savedParamSettings
;
1823 if (GetParent() != NULL
)
1824 GetParent()->SetFocus();
1830 SetReturnCode(0); // added so BoundsChecker would not report use of uninitialized variable
1833 } // CparameterDlg::OnCloseWindow()
1836 void CparameterDlg::OnButton( wxCommandEvent
&event
)
1838 wxWindow
*win
= (wxWindow
*) event
.GetEventObject();
1839 OnCommand( *win
, event
);
1843 void CparameterDlg::OnCommand(wxWindow
& win
, wxCommandEvent
& event
)
1845 wxString widgetName
;
1847 widgetName
= win
.GetName();
1852 if (widgetName
== pParamSaveBtn
->GetName())
1857 tStr
= wxT("Database parameters have been saved.");
1858 if (GetParent() != NULL
) // The parameter dialog was not called during startup due to a missing cfg file
1859 tStr
+= wxT("\nNew parameters will take effect the next time the program is started.");
1860 wxMessageBox(tStr
,wxT("Notice..."),wxOK
| wxICON_INFORMATION
);
1867 if (widgetName
== pParamCancelBtn
->GetName())
1872 } // CparameterDlg::OnCommand()
1875 bool CparameterDlg::PutData()
1877 // Fill the data source list box
1878 FillDataSourceList();
1880 // Fill in the fields from the params object
1881 if (wxGetApp().params
.ODBCSource
&& wxStrlen(wxGetApp().params
.ODBCSource
))
1882 pParamODBCSourceList
->SetStringSelection(wxGetApp().params
.ODBCSource
);
1883 pParamUserNameTxt
->SetValue(wxGetApp().params
.UserName
);
1884 pParamPasswordTxt
->SetValue(wxGetApp().params
.Password
);
1885 pParamDirPathTxt
->SetValue(wxGetApp().params
.DirPath
);
1887 } // CparameterDlg::PutData()
1890 bool CparameterDlg::GetData()
1893 if (pParamODBCSourceList
->GetStringSelection() != wxT(""))
1895 tStr
= pParamODBCSourceList
->GetStringSelection();
1896 if (tStr
.Length() > (sizeof(wxGetApp().params
.ODBCSource
)-1))
1899 errmsg
.Printf(wxT("ODBC Data source name is longer than the data structure to hold it.\n'Cparameter.ODBCSource' must have a larger character array\nto handle a data source with this long of a name\n\nThe data source currently selected is %d characters long."),tStr
.Length());
1900 wxMessageBox(errmsg
,wxT("Internal program error..."),wxOK
| wxICON_EXCLAMATION
);
1903 wxStrcpy(wxGetApp().params
.ODBCSource
, tStr
);
1908 tStr
= pParamUserNameTxt
->GetValue();
1909 if (tStr
.Length() > (sizeof(wxGetApp().params
.UserName
)-1))
1912 errmsg
.Printf(wxT("User name is longer than the data structure to hold it.\n'Cparameter.UserName' must have a larger character array\nto handle a data source with this long of a name\n\nThe user name currently specified is %d characters long."),tStr
.Length());
1913 wxMessageBox(errmsg
,wxT("Internal program error..."),wxOK
| wxICON_EXCLAMATION
);
1916 wxStrcpy(wxGetApp().params
.UserName
, tStr
);
1918 tStr
= pParamPasswordTxt
->GetValue();
1919 if (tStr
.Length() > (sizeof(wxGetApp().params
.Password
)-1))
1922 errmsg
.Printf(wxT("Password is longer than the data structure to hold it.\n'Cparameter.Password' must have a larger character array\nto handle a data source with this long of a name\n\nThe password currently specified is %d characters long."),tStr
.Length());
1923 wxMessageBox(errmsg
,wxT("Internal program error..."),wxOK
| wxICON_EXCLAMATION
);
1926 wxStrcpy(wxGetApp().params
.Password
,tStr
);
1928 tStr
= pParamDirPathTxt
->GetValue();
1929 tStr
.Replace(wxT("\\"),wxT("/"));
1930 if (tStr
.Length() > (sizeof(wxGetApp().params
.DirPath
)-1))
1933 errmsg
.Printf(wxT("DirPath is longer than the data structure to hold it.\n'Cparameter.DirPath' must have a larger character array\nto handle a data source with this long of a name\n\nThe password currently specified is %d characters long."),tStr
.Length());
1934 wxMessageBox(errmsg
,wxT("Internal program error..."),wxOK
| wxICON_EXCLAMATION
);
1937 wxStrcpy(wxGetApp().params
.DirPath
,tStr
);
1939 } // CparameterDlg::GetData()
1942 bool CparameterDlg::Save()
1944 // Copy the current params in case user cancels changing
1945 // the params, so that we can reset them.
1948 wxGetApp().params
= savedParamSettings
;
1952 wxGetApp().WriteParamFile(wxGetApp().params
);
1955 } // CparameterDlg::Save()
1958 void CparameterDlg::FillDataSourceList()
1960 wxChar Dsn
[SQL_MAX_DSN_LENGTH
+ 1];
1962 wxStringList strList
;
1964 while (wxDbGetDataSource(wxGetApp().DbConnectInf
->GetHenv(), Dsn
,
1965 SQL_MAX_DSN_LENGTH
+1, DsDesc
, 255))
1969 strList
.Add(wxT(""));
1970 wxChar
**p
= strList
.ListToArray();
1973 for (i
= 0; wxStrlen(p
[i
]); i
++)
1974 pParamODBCSourceList
->Append(p
[i
]);
1977 } // CparameterDlg::FillDataSourceList()
1980 BEGIN_EVENT_TABLE(CqueryDlg
, wxDialog
)
1981 EVT_BUTTON(-1, CqueryDlg::OnButton
)
1982 EVT_CLOSE(CqueryDlg::OnCloseWindow
)
1986 // CqueryDlg() constructor
1987 CqueryDlg::CqueryDlg(wxWindow
*parent
, wxDb
*pDb
, wxChar
*tblName
[],
1988 const wxString
&pWhereArg
) :
1989 wxDialog (parent
, QUERY_DIALOG
, wxT("Query"), wxPoint(-1, -1), wxSize(480, 360))
1991 wxBeginBusyCursor();
1995 masterTableName
= tblName
[0];
1996 widgetPtrsSet
= FALSE
;
1999 // Initialize the WHERE clause from the string passed in
2000 pWhere
= pWhereArg
; // Save a pointer to the output buffer
2001 if (pWhere
.Length() > (unsigned int)DB_MAX_WHERE_CLAUSE_LEN
) // Check the length of the buffer passed in
2004 s
.Printf(wxT("Maximum where clause length exceeded.\nLength must be less than %d"), DB_MAX_WHERE_CLAUSE_LEN
+1);
2005 wxMessageBox(s
,wxT("Error..."),wxOK
| wxICON_EXCLAMATION
);
2010 pQueryCol1Msg
= new wxStaticText(this, QUERY_DIALOG_COL_MSG
, wxT("Column 1:"), wxPoint( 10, 10), wxSize( 69, 16), 0, wxT("QueryCol1Msg"));
2011 pQueryCol1Choice
= new wxChoice(this, QUERY_DIALOG_COL_CHOICE
, wxPoint( 10, 27), wxSize(250, 27), 0, 0, 0, wxDefaultValidator
, wxT("QueryCol1Choice"));
2012 pQueryNotMsg
= new wxStaticText(this, QUERY_DIALOG_NOT_MSG
, wxT("NOT"), wxPoint(268, 10), wxSize( -1, -1), 0, wxT("QueryNotMsg"));
2013 pQueryNotCheck
= new wxCheckBox(this, QUERY_DIALOG_NOT_CHECKBOX
, wxT(""), wxPoint(275, 37), wxSize( 20, 20), 0, wxDefaultValidator
, wxT("QueryNotCheck"));
2015 wxString choice_strings
[9];
2016 choice_strings
[0] = wxT("=");
2017 choice_strings
[1] = wxT("<");
2018 choice_strings
[2] = wxT(">");
2019 choice_strings
[3] = wxT("<=");
2020 choice_strings
[4] = wxT(">=");
2021 choice_strings
[5] = wxT("Begins");
2022 choice_strings
[6] = wxT("Contains");
2023 choice_strings
[7] = wxT("Like");
2024 choice_strings
[8] = wxT("Between");
2026 pQueryOperatorMsg
= new wxStaticText(this, QUERY_DIALOG_OP_MSG
, wxT("Operator:"), wxPoint(305, 10), wxSize( -1, -1), 0, wxT("QueryOperatorMsg"));
2027 pQueryOperatorChoice
= new wxChoice(this, QUERY_DIALOG_OP_CHOICE
, wxPoint(305, 27), wxSize( 80, 27), 9, choice_strings
, 0, wxDefaultValidator
, wxT("QueryOperatorChoice"));
2028 pQueryCol2Msg
= new wxStaticText(this, QUERY_DIALOG_COL2_MSG
, wxT("Column 2:"), wxPoint( 10, 65), wxSize( 69, 16), 0, wxT("QueryCol2Msg"));
2029 pQueryCol2Choice
= new wxChoice(this, QUERY_DIALOG_COL2_CHOICE
, wxPoint( 10, 82), wxSize(250, 27), 0, 0, 0, wxDefaultValidator
, wxT("QueryCol2Choice"));
2030 pQuerySqlWhereMsg
= new wxStaticText(this, QUERY_DIALOG_WHERE_MSG
, wxT("SQL where clause:"), wxPoint( 10, 141), wxSize( -1, -1), 0, wxT("QuerySqlWhereMsg"));
2031 pQuerySqlWhereMtxt
= new wxTextCtrl(this, QUERY_DIALOG_WHERE_TEXT
, wxT(""), wxPoint( 10, 159), wxSize(377, 134), wxTE_MULTILINE
, wxDefaultValidator
, wxT("QuerySqlWhereMtxt"));
2032 pQueryAddBtn
= new wxButton(this, QUERY_DIALOG_ADD
, wxT("&Add"), wxPoint(406, 24), wxSize( 56, 26), 0, wxDefaultValidator
, wxT("QueryAddBtn"));
2033 pQueryAndBtn
= new wxButton(this, QUERY_DIALOG_AND
, wxT("A&nd"), wxPoint(406, 58), wxSize( 56, 26), 0, wxDefaultValidator
, wxT("QueryAndBtn"));
2034 pQueryOrBtn
= new wxButton(this, QUERY_DIALOG_OR
, wxT("&Or"), wxPoint(406, 92), wxSize( 56, 26), 0, wxDefaultValidator
, wxT("QueryOrBtn"));
2035 pQueryLParenBtn
= new wxButton(this, QUERY_DIALOG_LPAREN
, wxT("("), wxPoint(406, 126), wxSize( 26, 26), 0, wxDefaultValidator
, wxT("QueryLParenBtn"));
2036 pQueryRParenBtn
= new wxButton(this, QUERY_DIALOG_RPAREN
, wxT(")"), wxPoint(436, 126), wxSize( 26, 26), 0, wxDefaultValidator
, wxT("QueryRParenBtn"));
2037 pQueryDoneBtn
= new wxButton(this, QUERY_DIALOG_DONE
, wxT("&Done"), wxPoint(406, 185), wxSize( 56, 26), 0, wxDefaultValidator
, wxT("QueryDoneBtn"));
2038 pQueryClearBtn
= new wxButton(this, QUERY_DIALOG_CLEAR
, wxT("C&lear"), wxPoint(406, 218), wxSize( 56, 26), 0, wxDefaultValidator
, wxT("QueryClearBtn"));
2039 pQueryCountBtn
= new wxButton(this, QUERY_DIALOG_COUNT
, wxT("&Count"), wxPoint(406, 252), wxSize( 56, 26), 0, wxDefaultValidator
, wxT("QueryCountBtn"));
2040 pQueryValue1Msg
= new wxStaticText(this, QUERY_DIALOG_VALUE1_MSG
, wxT("Value:"), wxPoint(277, 66), wxSize( -1, -1), 0, wxT("QueryValue1Msg"));
2041 pQueryValue1Txt
= new wxTextCtrl(this, QUERY_DIALOG_VALUE1_TEXT
, wxT(""), wxPoint(277, 83), wxSize(108, 25), 0, wxDefaultValidator
, wxT("QueryValue1Txt"));
2042 pQueryValue2Msg
= new wxStaticText(this, QUERY_DIALOG_VALUE2_MSG
, wxT("AND"), wxPoint(238, 126), wxSize( -1, -1), 0, wxT("QueryValue2Msg"));
2043 pQueryValue2Txt
= new wxTextCtrl(this, QUERY_DIALOG_VALUE2_TEXT
, wxT(""), wxPoint(277, 120), wxSize(108, 25), 0, wxDefaultValidator
, wxT("QueryValue2Txt"));
2044 pQueryHintGrp
= new wxStaticBox(this, QUERY_DIALOG_HINT_GROUP
, wxT(""), wxPoint( 10, 291), wxSize(377, 40), 0, wxT("QueryHintGrp"));
2045 pQueryHintMsg
= new wxStaticText(this, QUERY_DIALOG_HINT_MSG
, wxT(""), wxPoint( 16, 306), wxSize( -1, -1), 0, wxT("QueryHintMsg"));
2047 widgetPtrsSet
= TRUE
;
2048 // Initialize the dialog
2050 pQueryCol2Choice
->Append(wxT("VALUE -->"));
2051 colInf
= pDB
->GetColumns(tblName
);
2057 tStr
= wxT("ODBC error during GetColumns()\n\n");
2058 tStr
+= GetExtendedDBErrorMsg(pDb
,__FILE__
,__LINE__
);
2059 wxMessageBox(tStr
,wxT("ODBC Error..."),wxOK
| wxICON_EXCLAMATION
);
2064 for (i
= 0; colInf
[i
].colName
&& wxStrlen(colInf
[i
].colName
); i
++)
2066 // If there is more than one table being queried, qualify
2067 // the column names with the table name prefix.
2068 if (tblName
[1] && wxStrlen(tblName
[1]))
2070 qualName
.Printf(wxT("%s.%s"), colInf
[i
].tableName
, colInf
[i
].colName
);
2071 pQueryCol1Choice
->Append(qualName
);
2072 pQueryCol2Choice
->Append(qualName
);
2074 else // Single table query, append just the column names
2076 pQueryCol1Choice
->Append(colInf
[i
].colName
);
2077 pQueryCol2Choice
->Append(colInf
[i
].colName
);
2081 pQueryCol1Choice
->SetSelection(0);
2082 pQueryCol2Choice
->SetSelection(0);
2083 pQueryOperatorChoice
->SetSelection(0);
2085 pQueryValue2Msg
->Show(FALSE
);
2086 pQueryValue2Txt
->Show(FALSE
);
2088 pQueryHintMsg
->SetLabel(langQRY_EQ
);
2090 pQuerySqlWhereMtxt
->SetValue(pWhere
.c_str());
2094 // Display the dialog window
2097 } // CqueryDlg() constructor
2100 CqueryDlg::~CqueryDlg()
2102 } // CqueryDlg::~CqueryDlg() destructor
2105 void CqueryDlg::OnButton(wxCommandEvent
&event
)
2107 wxWindow
*win
= (wxWindow
*) event
.GetEventObject();
2108 OnCommand( *win
, event
);
2109 } // CqueryDlg::OnButton()
2112 void CqueryDlg::OnCommand(wxWindow
& win
, wxCommandEvent
& event
)
2114 // Widget pointers won't be set when the dialog is constructed.
2115 // Control is passed through this function once for each widget on
2116 // a dialog as the dialog is constructed.
2120 wxString widgetName
= win
.GetName();
2122 // Operator choice box
2123 if (widgetName
== pQueryOperatorChoice
->GetName())
2125 // Set the help text
2126 switch((qryOp
) pQueryOperatorChoice
->GetSelection())
2129 pQueryHintMsg
->SetLabel(langQRY_EQ
);
2132 pQueryHintMsg
->SetLabel(langQRY_LT
);
2135 pQueryHintMsg
->SetLabel(langQRY_GT
);
2138 pQueryHintMsg
->SetLabel(langQRY_LE
);
2141 pQueryHintMsg
->SetLabel(langQRY_GE
);
2144 pQueryHintMsg
->SetLabel(langQRY_BEGINS
);
2147 pQueryHintMsg
->SetLabel(langQRY_CONTAINS
);
2150 pQueryHintMsg
->SetLabel(langQRY_LIKE
);
2153 pQueryHintMsg
->SetLabel(langQRY_BETWEEN
);
2157 // Hide the value2 widget
2158 pQueryValue2Msg
->Show(FALSE
); // BETWEEN will show this widget
2159 pQueryValue2Txt
->Show(FALSE
); // BETWEEN will show this widget
2161 // Disable the NOT operator for <, <=, >, >=
2162 switch((qryOp
) pQueryOperatorChoice
->GetSelection())
2168 pQueryNotCheck
->SetValue(0);
2169 pQueryNotCheck
->Enable(FALSE
);
2172 pQueryNotCheck
->Enable(TRUE
);
2176 // Manipulate the dialog to handle the selected operator
2177 switch((qryOp
) pQueryOperatorChoice
->GetSelection())
2184 pQueryCol2Choice
->Enable(TRUE
);
2185 if (pQueryCol2Choice
->GetSelection()) // Column name is highlighted
2187 pQueryValue1Msg
->Show(FALSE
);
2188 pQueryValue1Txt
->Show(FALSE
);
2190 else // "Value" is highlighted
2192 pQueryValue1Msg
->Show(TRUE
);
2193 pQueryValue1Txt
->Show(TRUE
);
2194 pQueryValue1Txt
->SetFocus();
2200 pQueryCol2Choice
->SetSelection(0);
2201 pQueryCol2Choice
->Enable(FALSE
);
2202 pQueryValue1Msg
->Show(TRUE
);
2203 pQueryValue1Txt
->Show(TRUE
);
2204 pQueryValue1Txt
->SetFocus();
2207 pQueryCol2Choice
->SetSelection(0);
2208 pQueryCol2Choice
->Enable(FALSE
);
2209 pQueryValue2Msg
->Show(TRUE
);
2210 pQueryValue2Txt
->Show(TRUE
);
2211 pQueryValue1Msg
->Show(TRUE
);
2212 pQueryValue1Txt
->Show(TRUE
);
2213 pQueryValue1Txt
->SetFocus();
2219 } // Operator choice box
2222 if (widgetName
== pQueryCol2Choice
->GetName())
2224 if (pQueryCol2Choice
->GetSelection()) // Column name is highlighted
2226 pQueryValue1Msg
->Show(FALSE
);
2227 pQueryValue1Txt
->Show(FALSE
);
2229 else // "Value" is highlighted
2231 pQueryValue1Msg
->Show(TRUE
);
2232 pQueryValue1Txt
->Show(TRUE
);
2233 pQueryValue1Txt
->SetFocus();
2236 } // Column 2 choice
2239 if (widgetName
== pQueryAddBtn
->GetName())
2246 if (widgetName
== pQueryAndBtn
->GetName())
2248 AppendToWhere(wxT(" AND\n"));
2253 if (widgetName
== pQueryOrBtn
->GetName())
2255 AppendToWhere(wxT(" OR\n"));
2259 // Left Paren button
2260 if (widgetName
== pQueryLParenBtn
->GetName())
2262 AppendToWhere(wxT("("));
2264 } // Left Paren button
2266 // Right paren button
2267 if (widgetName
== pQueryRParenBtn
->GetName())
2269 AppendToWhere(wxT(")"));
2271 } // Right Paren button
2274 if (widgetName
== pQueryDoneBtn
->GetName())
2276 // Be sure the where clause will not overflow the output buffer
2277 if (wxStrlen(pQuerySqlWhereMtxt
->GetValue()) > (unsigned int)DB_MAX_WHERE_CLAUSE_LEN
)
2280 s
.Printf(wxT("Maximum where clause length exceeded.\nLength must be less than %d"), DB_MAX_WHERE_CLAUSE_LEN
+1);
2281 wxMessageBox(s
,wxT("Error..."),wxOK
| wxICON_EXCLAMATION
);
2284 // Validate the where clause for things such as matching parens
2285 if (!ValidateWhereClause())
2287 // Copy the where clause to the output buffer and exit
2288 pWhere
= pQuerySqlWhereMtxt
->GetValue();
2294 if (widgetName
== pQueryClearBtn
->GetName())
2296 bool Ok
= (wxMessageBox(wxT("Are you sure you wish to clear the Query?"),wxT("Confirm"),wxYES_NO
|wxICON_QUESTION
) == wxYES
);
2299 pQuerySqlWhereMtxt
->SetValue(wxT(""));
2304 if (widgetName
== pQueryCountBtn
->GetName())
2306 wxBeginBusyCursor();
2312 } // CqueryDlg::OnCommand
2315 void CqueryDlg::OnCloseWindow(wxCloseEvent
& event
)
2322 GetParent()->SetFocus();
2327 SetReturnCode(1); // added so BoundsChecker would not report use of uninitialized variable
2330 } // CqueryDlg::OnCloseWindow()
2333 void CqueryDlg::AppendToWhere(wxChar
*s
)
2335 wxString whereStr
= pQuerySqlWhereMtxt
->GetValue();
2337 pQuerySqlWhereMtxt
->SetValue(whereStr
);
2338 } // CqueryDlg::AppendToWhere()
2341 void CqueryDlg::ProcessAddBtn()
2343 qryOp oper
= (qryOp
) pQueryOperatorChoice
->GetSelection();
2345 // Verify that eveything is filled in correctly
2346 if (pQueryCol2Choice
->GetSelection() == 0) // "Value" is selected
2348 // Verify that value 1 is filled in
2349 if (wxStrlen(pQueryValue1Txt
->GetValue()) == 0)
2352 pQueryValue1Txt
->SetFocus();
2355 // For the BETWEEN operator, value 2 must be filled in as well
2356 if (oper
== qryOpBETWEEN
&&
2357 wxStrlen(pQueryValue2Txt
->GetValue()) == 0)
2360 pQueryValue2Txt
->SetFocus();
2365 // Build the expression and append it to the where clause window
2366 wxString s
= pQueryCol1Choice
->GetStringSelection();
2368 if (pQueryNotCheck
->GetValue() && (oper
!= qryOpEQ
))
2374 if (pQueryNotCheck
->GetValue()) // NOT box is checked
2397 s
+= wxT(" BETWEEN");
2403 int col1Idx
= pQueryCol1Choice
->GetSelection();
2406 if (colInf
[col1Idx
].sqlDataType
== SQL_VARCHAR
||
2407 oper
== qryOpBEGINS
||
2408 oper
== qryOpCONTAINS
||
2412 if (pQueryCol2Choice
->GetSelection()) // Column name
2413 s
+= pQueryCol2Choice
->GetStringSelection();
2414 else // Column 2 is a "value"
2418 if (oper
== qryOpCONTAINS
)
2420 s
+= pQueryValue1Txt
->GetValue();
2421 if (oper
== qryOpCONTAINS
|| oper
== qryOpBEGINS
)
2427 if (oper
== qryOpBETWEEN
)
2432 s
+= pQueryValue2Txt
->GetValue();
2437 AppendToWhere((wxChar
*) (const wxChar
*) s
);
2439 } // CqueryDlg::ProcessAddBtn()
2442 void CqueryDlg::ProcessCountBtn()
2444 if (!ValidateWhereClause())
2447 if (!dbTable
) // wxDbTable object needs to be created and opened
2449 dbTable
= new wxDbTable(pDB
, masterTableName
, 0, wxT(""),
2451 wxGetApp().DbConnectInf
->GetDefaultDir());
2454 wxMessageBox(wxT("Memory allocation failed creating a wxDbTable object."),wxT("Error..."),wxOK
| wxICON_EXCLAMATION
);
2457 if (!dbTable
->Open())
2460 tStr
= wxT("ODBC error during Open()\n\n");
2461 tStr
+= GetExtendedDBErrorMsg(dbTable
->GetDb(),__FILE__
,__LINE__
);
2462 wxMessageBox(tStr
,wxT("ODBC Error..."),wxOK
| wxICON_EXCLAMATION
);
2467 // Count() with WHERE clause
2470 whereStr
= pQuerySqlWhereMtxt
->GetValue();
2471 dbTable
->SetWhereClause(whereStr
.c_str());
2473 ULONG whereCnt
= dbTable
->Count();
2475 // Count() of all records in the table
2476 dbTable
->SetWhereClause(wxT(""));
2477 ULONG totalCnt
= dbTable
->Count();
2479 if (whereCnt
> 0 || totalCnt
== 0)
2482 tStr
.Printf(wxT("%lu of %lu records match the query criteria."),whereCnt
,totalCnt
);
2483 wxMessageBox(tStr
,wxT("Notice..."),wxOK
| wxICON_INFORMATION
);
2488 tStr
.Printf(wxT("%lu of %lu records match the query criteria.\n\nEither the criteria entered produced a result set\nwith no records, or there was a syntactical error\nin the clause you entered.\n\nPress the details button to see if any database errors were reported."),whereCnt
,totalCnt
);
2489 wxMessageBox(tStr
,wxT("Notice..."),wxOK
| wxICON_INFORMATION
);
2492 // After a wxMessageBox, the focus does not necessarily return to the
2493 // window which was the focus when the message box popped up, so return
2494 // focus to the Query dialog for certain
2497 } // CqueryDlg::ProcessCountBtn()
2500 bool CqueryDlg::ValidateWhereClause()
2502 wxString where
= pQuerySqlWhereMtxt
->GetValue();
2504 if (where
.Freq(wxT('(')) != where
.Freq(wxT(')')))
2506 wxMessageBox(wxT("There are mismatched parenthesis in the constructed where clause"),wxT("Error..."),wxOK
| wxICON_EXCLAMATION
);
2509 // After a wxMessageBox, the focus does not necessarily return to the
2510 // window which was the focus when the message box popped up, so return
2511 // focus to the Query dialog for certain
2516 } // CqueryDlg::ValidateWhereClause()
2520 void DisplayDbDiagnostics(wxDb
*pDb
)
2525 s
= langDBINF_DB_NAME
;
2526 s
+= pDb
->dbInf
.dbmsName
;
2529 s
+= langDBINF_DB_VER
;
2530 s
+= pDb
->dbInf
.dbmsVer
;
2533 s
+= langDBINF_DRIVER_NAME
;
2534 s
+= pDb
->dbInf
.driverName
;
2537 s
+= langDBINF_DRIVER_ODBC_VER
;
2538 s
+= pDb
->dbInf
.odbcVer
;
2541 s
+= langDBINF_DRIVER_MGR_ODBC_VER
;
2542 s
+= pDb
->dbInf
.drvMgrOdbcVer
;
2545 s
+= langDBINF_DRIVER_VER
;
2546 s
+= pDb
->dbInf
.driverVer
;
2549 s
+= langDBINF_SERVER_NAME
;
2550 s
+= pDb
->dbInf
.serverName
;
2553 s
+= langDBINF_FILENAME
;
2554 s
+= pDb
->dbInf
.databaseName
;
2557 s
+= langDBINF_OUTER_JOINS
;
2558 s
+= pDb
->dbInf
.outerJoins
;
2561 s
+= langDBINF_STORED_PROC
;
2562 s
+= pDb
->dbInf
.procedureSupport
;
2565 if (pDb
->dbInf
.maxConnections
)
2566 t
.sprintf("%s%d\n", langDBINF_MAX_HDBC
, pDb
->dbInf
.maxConnections
);
2568 t
.sprintf("%s%s\n", langDBINF_MAX_HDBC
, langDBINF_UNLIMITED
);
2571 if (pDb
->dbInf
.maxStmts
)
2572 t
.sprintf("%s%d\n", langDBINF_MAX_HSTMT
, pDb
->dbInf
.maxStmts
);
2574 t
.sprintf("%s%s\n", langDBINF_MAX_HSTMT
, langDBINF_UNLIMITED
);
2577 s
+= langDBINF_API_LVL
;
2578 switch(pDb
->dbInf
.apiConfLvl
)
2580 case SQL_OAC_NONE
: s
+= langDBINF_NONE
; break;
2581 case SQL_OAC_LEVEL1
: s
+= langDBINF_LEVEL1
; break;
2582 case SQL_OAC_LEVEL2
: s
+= langDBINF_LEVEL2
; break;
2586 s
+= langDBINF_CLI_LVL
;
2587 switch(pDb
->dbInf
.cliConfLvl
)
2589 case SQL_OSCC_NOT_COMPLIANT
: s
+= langDBINF_NOT_COMPLIANT
; break;
2590 case SQL_OSCC_COMPLIANT
: s
+= langDBINF_COMPLIANT
; break;
2594 s
+= langDBINF_SQL_LVL
;
2595 switch(pDb
->dbInf
.sqlConfLvl
)
2597 case SQL_OSC_MINIMUM
: s
+= langDBINF_MIN_GRAMMAR
; break;
2598 case SQL_OSC_CORE
: s
+= langDBINF_CORE_GRAMMAR
; break;
2599 case SQL_OSC_EXTENDED
: s
+= langDBINF_EXT_GRAMMAR
; break;
2603 s
+= langDBINF_COMMIT_BEHAVIOR
;
2604 switch(pDb
->dbInf
.cursorCommitBehavior
)
2606 case SQL_CB_DELETE
: s
+= langDBINF_DELETE_CURSORS
; break;
2607 case SQL_CB_CLOSE
: s
+= langDBINF_CLOSE_CURSORS
; break;
2608 case SQL_CB_PRESERVE
: s
+= langDBINF_PRESERVE_CURSORS
; break;
2612 s
+= langDBINF_ROLLBACK_BEHAVIOR
;
2613 switch(pDb
->dbInf
.cursorRollbackBehavior
)
2615 case SQL_CB_DELETE
: s
+= langDBINF_DELETE_CURSORS
; break;
2616 case SQL_CB_CLOSE
: s
+= langDBINF_CLOSE_CURSORS
; break;
2617 case SQL_CB_PRESERVE
: s
+= langDBINF_PRESERVE_CURSORS
; break;
2621 s
+= langDBINF_SUPP_NOT_NULL
;
2622 switch(pDb
->dbInf
.supportNotNullClause
)
2624 case SQL_NNC_NULL
: s
+= langNO
; break;
2625 case SQL_NNC_NON_NULL
: s
+= langYES
; break;
2629 s
+= langDBINF_SUPP_IEF
;
2630 s
+= pDb
->dbInf
.supportIEF
;
2633 // DEFAULT setting for "Transaction Isolation Level"
2634 s
+= langDBINF_TXN_ISOLATION
;
2635 switch(pDb
->dbInf
.txnIsolation
)
2637 case SQL_TXN_READ_UNCOMMITTED
: s
+= langDBINF_READ_UNCOMMITTED
; break;
2638 case SQL_TXN_READ_COMMITTED
: s
+= langDBINF_READ_COMMITTED
; break;
2639 case SQL_TXN_REPEATABLE_READ
: s
+= langDBINF_REPEATABLE_READ
; break;
2640 case SQL_TXN_SERIALIZABLE
: s
+= langDBINF_SERIALIZABLE
; break;
2642 case SQL_TXN_VERSIONING
: s
+= langDBINF_VERSIONING
; break;
2647 // CURRENT setting for "Transaction Isolation Level"
2649 s
+= langDBINF_TXN_ISOLATION_CURR
;
2650 if (SQLGetConnectOption(pDb
->GetHDBC(),SQL_TXN_ISOLATION
,&txnIsoLvl
) == SQL_SUCCESS
)
2654 case SQL_TXN_READ_UNCOMMITTED
: s
+= langDBINF_READ_UNCOMMITTED
; break;
2655 case SQL_TXN_READ_COMMITTED
: s
+= langDBINF_READ_COMMITTED
; break;
2656 case SQL_TXN_REPEATABLE_READ
: s
+= langDBINF_REPEATABLE_READ
; break;
2657 case SQL_TXN_SERIALIZABLE
: s
+= langDBINF_SERIALIZABLE
; break;
2659 case SQL_TXN_VERSIONING
: s
+= langDBINF_VERSIONING
; break;
2666 s
+= langDBINF_TXN_ISOLATION_OPTS
;
2667 if (pDb
->dbInf
.txnIsolationOptions
& SQL_TXN_READ_UNCOMMITTED
)
2668 {s
+= langDBINF_READ_UNCOMMITTED
; comma
++;}
2669 if (pDb
->dbInf
.txnIsolationOptions
& SQL_TXN_READ_COMMITTED
)
2670 {if (comma
++) s
+= ", "; s
+= langDBINF_READ_COMMITTED
;}
2671 if (pDb
->dbInf
.txnIsolationOptions
& SQL_TXN_REPEATABLE_READ
)
2672 {if (comma
++) s
+= ", "; s
+= langDBINF_REPEATABLE_READ
;}
2673 if (pDb
->dbInf
.txnIsolationOptions
& SQL_TXN_SERIALIZABLE
)
2674 {if (comma
++) s
+= ", "; s
+= langDBINF_SERIALIZABLE
;}
2676 if (pDb
->dbInf
.txnIsolationOptions
& SQL_TXN_VERSIONING
)
2677 {if (comma
++) s
+= ", "; s
+= langDBINF_VERSIONING
;}
2682 s
+= langDBINF_FETCH_DIRS
;
2683 if (pDb
->dbInf
.fetchDirections
& SQL_FD_FETCH_NEXT
)
2684 {s
+= langDBINF_NEXT
; comma
++;}
2685 if (pDb
->dbInf
.fetchDirections
& SQL_FD_FETCH_PRIOR
)
2686 {if (comma
++) s
+= ", "; s
+= langDBINF_PREV
;}
2687 if (pDb
->dbInf
.fetchDirections
& SQL_FD_FETCH_FIRST
)
2688 {if (comma
++) s
+= ", "; s
+= langDBINF_FIRST
;}
2689 if (pDb
->dbInf
.fetchDirections
& SQL_FD_FETCH_LAST
)
2690 {if (comma
++) s
+= ", "; s
+= langDBINF_LAST
;}
2691 if (pDb
->dbInf
.fetchDirections
& SQL_FD_FETCH_ABSOLUTE
)
2692 {if (comma
++) s
+= ", "; s
+= langDBINF_ABSOLUTE
;}
2693 if (pDb
->dbInf
.fetchDirections
& SQL_FD_FETCH_RELATIVE
)
2694 {if (comma
++) s
+= ", "; s
+= langDBINF_RELATIVE
;}
2696 if (pDb
->dbInf
.fetchDirections
& SQL_FD_FETCH_RESUME
)
2697 {if (comma
++) s
+= ", "; s
+= langDBINF_RESUME
;}
2699 if (pDb
->dbInf
.fetchDirections
& SQL_FD_FETCH_BOOKMARK
)
2700 {if (comma
++) s
+= ", "; s
+= langDBINF_BOOKMARK
;}
2704 s
+= langDBINF_LOCK_TYPES
;
2705 if (pDb
->dbInf
.lockTypes
& SQL_LCK_NO_CHANGE
)
2706 {s
+= langDBINF_NO_CHANGE
; comma
++;}
2707 if (pDb
->dbInf
.lockTypes
& SQL_LCK_EXCLUSIVE
)
2708 {if (comma
++) s
+= ", "; s
+= langDBINF_EXCLUSIVE
;}
2709 if (pDb
->dbInf
.lockTypes
& SQL_LCK_UNLOCK
)
2710 {if (comma
++) s
+= ", "; s
+= langDBINF_UNLOCK
;}
2714 s
+= langDBINF_POS_OPERS
;
2715 if (pDb
->dbInf
.posOperations
& SQL_POS_POSITION
)
2716 {s
+= langDBINF_POSITION
; comma
++;}
2717 if (pDb
->dbInf
.posOperations
& SQL_POS_REFRESH
)
2718 {if (comma
++) s
+= ", "; s
+= langDBINF_REFRESH
;}
2719 if (pDb
->dbInf
.posOperations
& SQL_POS_UPDATE
)
2720 {if (comma
++) s
+= ", "; s
+= langDBINF_UPD
;}
2721 if (pDb
->dbInf
.posOperations
& SQL_POS_DELETE
)
2722 {if (comma
++) s
+= ", "; s
+= langDBINF_DEL
;}
2723 if (pDb
->dbInf
.posOperations
& SQL_POS_ADD
)
2724 {if (comma
++) s
+= ", "; s
+= langDBINF_ADD
;}
2728 s
+= langDBINF_POS_STMTS
;
2729 if (pDb
->dbInf
.posStmts
& SQL_PS_POSITIONED_DELETE
)
2730 {s
+= langDBINF_POS_DEL
; comma
++;}
2731 if (pDb
->dbInf
.posStmts
& SQL_PS_POSITIONED_UPDATE
)
2732 {if (comma
++) s
+= ", "; s
+= langDBINF_POS_UPD
;}
2733 if (pDb
->dbInf
.posStmts
& SQL_PS_SELECT_FOR_UPDATE
)
2734 {if (comma
++) s
+= ", "; s
+= langDBINF_SELECT_FOR_UPD
;}
2738 s
+= langDBINF_SCROLL_CONCURR
;
2739 if (pDb
->dbInf
.scrollConcurrency
& SQL_SCCO_READ_ONLY
)
2740 {s
+= langDBINF_READ_ONLY
; comma
++;}
2741 if (pDb
->dbInf
.scrollConcurrency
& SQL_SCCO_LOCK
)
2742 {if (comma
++) s
+= ", "; s
+= langDBINF_LOCK
;}
2743 if (pDb
->dbInf
.scrollConcurrency
& SQL_SCCO_OPT_ROWVER
)
2744 {if (comma
++) s
+= ", "; s
+= langDBINF_OPT_ROWVER
;}
2745 if (pDb
->dbInf
.scrollConcurrency
& SQL_SCCO_OPT_VALUES
)
2746 {if (comma
++) s
+= ", "; s
+= langDBINF_OPT_VALUES
;}
2750 s
+= langDBINF_SCROLL_OPTS
;
2751 if (pDb
->dbInf
.scrollOptions
& SQL_SO_FORWARD_ONLY
)
2752 {s
+= langDBINF_FWD_ONLY
; comma
++;}
2753 if (pDb
->dbInf
.scrollOptions
& SQL_SO_STATIC
)
2754 {if (comma
++) s
+= ", "; s
+= langDBINF_STATIC
;}
2755 if (pDb
->dbInf
.scrollOptions
& SQL_SO_KEYSET_DRIVEN
)
2756 {if (comma
++) s
+= ", "; s
+= langDBINF_KEYSET_DRIVEN
;}
2757 if (pDb
->dbInf
.scrollOptions
& SQL_SO_DYNAMIC
)
2758 {if (comma
++) s
+= ", "; s
+= langDBINF_DYNAMIC
;}
2759 if (pDb
->dbInf
.scrollOptions
& SQL_SO_MIXED
)
2760 {if (comma
++) s
+= ", "; s
+= langDBINF_MIXED
;}
2764 s
+= langDBINF_STATIC_SENS
;
2765 if (pDb
->dbInf
.staticSensitivity
& SQL_SS_ADDITIONS
)
2766 {s
+= langDBINF_ADDITIONS
; comma
++;}
2767 if (pDb
->dbInf
.staticSensitivity
& SQL_SS_DELETIONS
)
2768 {if (comma
++) s
+= ", "; s
+= langDBINF_DELETIONS
;}
2769 if (pDb
->dbInf
.staticSensitivity
& SQL_SS_UPDATES
)
2770 {if (comma
++) s
+= ", "; s
+= langDBINF_UPDATES
;}
2774 s
+= langDBINF_TXN_CAPABLE
;
2775 switch(pDb
->dbInf
.txnCapable
)
2777 case SQL_TC_NONE
: s
+= langNO
; break;
2778 case SQL_TC_DML
: s
+= langDBINF_DML_ONLY
; break;
2779 case SQL_TC_DDL_COMMIT
: s
+= langDBINF_DDL_COMMIT
; break;
2780 case SQL_TC_DDL_IGNORE
: s
+= langDBINF_DDL_IGNORE
; break;
2781 case SQL_TC_ALL
: s
+= langDBINF_DDL_AND_DML
; break;
2785 t
.sprintf("%s%d\n", langDBINF_LOGIN_TIMEOUT
, pDb
->dbInf
.loginTimeout
);
2788 // Oracle specific information
2789 if (pDb
->Dbms() == dbmsORACLE
)
2792 s
+= langDBINF_ORACLE_BANNER
;
2795 // Oracle cache hit ratio
2798 pDb
->ExecSql("SELECT VALUE FROM V$SYSSTAT WHERE NAME = 'db block gets'");
2800 if (pDb
->GetData(1, SQL_C_ULONG
, &dbBlockGets
, 0, &cb
))
2802 t
.sprintf("%s: %lu\n", langDBINF_DB_BLOCK_GETS
, dbBlockGets
);
2806 ULONG consistentGets
;
2807 pDb
->ExecSql("SELECT VALUE FROM V$SYSSTAT WHERE NAME = 'consistent gets'");
2809 if (pDb
->GetData(1, SQL_C_ULONG
, &consistentGets
, 0, &cb
))
2811 t
.sprintf("%s: %lu\n", langDBINF_CONSISTENT_GETS
, consistentGets
);
2816 pDb
->ExecSql("SELECT VALUE FROM V$SYSSTAT WHERE NAME = 'physical reads'");
2818 if (pDb
->GetData(1, SQL_C_ULONG
, &physReads
, 0, &cb
))
2820 t
.sprintf("%s: %lu\n", langDBINF_PHYSICAL_READS
, physReads
);
2824 ULONG hitRatio
= (ULONG
)((1.00 - ((float)physReads
/ (float)(dbBlockGets
+ consistentGets
))) * 100.00);
2825 t
.sprintf("*** %s: %lu%%\n", langDBINF_CACHE_HIT_RATIO
, hitRatio
);
2828 // Tablespace information
2830 s
+= langDBINF_TABLESPACE_IO
;
2833 char tablespaceName
[257];
2834 pDb
->ExecSql("SELECT NAME,PHYRDS,PHYWRTS FROM V$DATAFILE, V$FILESTAT WHERE V$DATAFILE.FILE# = V$FILESTAT.FILE#");
2835 while (pDb
->GetNext())
2837 pDb
->GetData(1, SQL_C_CHAR
, tablespaceName
, 257, &cb
);
2838 pDb
->GetData(2, SQL_C_ULONG
, &physReads
, 0, &cb
);
2839 pDb
->GetData(3, SQL_C_ULONG
, &physWrites
, 0, &cb
);
2840 t
.sprintf("%s\n\t%s: %lu\t%s: %lu\n", tablespaceName
,
2841 langDBINF_PHYSICAL_READS
, physReads
, langDBINF_PHYSICAL_WRITES
, physWrites
);
2850 } // DisplayDbDiagnostics()
2856 TEST CODE FOR TESTING THE wxDbCreateDataSource() FUNCTION
2859 result = wxDbCreateDataSource(wxT("Microsoft Access Driver (*.mdb)"),wxT("GLT-TEST2"),wxT("GLT-Descrip"),FALSE,wxT(""),this);
2862 // check for errors caused by ConfigDSN based functions
2865 wxChar errMsg[500+1];
2866 errMsg[0] = wxT('\0');
2868 SQLInstallerError(1,&retcode,errMsg,500,&cb);
2870 wxMessageBox(wxT("FAILED creating data source"),wxT("FAILED"));
2873 wxMessageBox(wxT("SUCCEEDED creating data source"),wxT("SUCCESS"));