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 */
51 #include <wx/generic/gridctrl.h>
52 #include <wx/dbgrid.h>
57 #include "dbtest.h" /* Header file for this demonstration program */
58 #include "listdb.h" /* Code to support the "Lookup" button on the editor dialog */
60 IMPLEMENT_APP(DatabaseDemoApp
)
62 extern wxChar ListDB_Selection
[]; /* Used to return the first column value for the selected line from the listDB routines */
63 extern wxChar ListDB_Selection2
[]; /* Used to return the second column value for the selected line from the listDB routines */
67 #error Sample cannot be compiled unless setup.h has wxUSE_ODBC set to 1
71 bool DataTypeSupported(wxDb
*pDb
, SWORD datatype
)
73 wxDbSqlTypeInfo sqlTypeInfo
;
75 bool breakpoint
= FALSE
;
77 if (pDb
->GetDataTypeInfo(datatype
, sqlTypeInfo
))
82 } // GetDataTypesSupported();
86 void CheckSupportForAllDataTypes(wxDb
*pDb
)
88 wxLogMessage("\nThe following datatypes are supported by the\ndatabase you are currently connected to:");
90 if (DataTypeSupported(pDb
,SQL_C_BINARY
))
91 wxLogMessage("SQL_C_BINARY");
94 if (DataTypeSupported(pDb
,SQL_C_BIT
))
95 wxLogMessage("SQL_C_BIT");
98 if (DataTypeSupported(pDb
,SQL_C_BOOKMARK
))
99 wxLogMessage("SQL_C_BOOKMARK");
102 if (DataTypeSupported(pDb
,SQL_C_CHAR
))
103 wxLogMessage("SQL_C_CHAR");
106 if (DataTypeSupported(pDb
,SQL_C_DATE
))
107 wxLogMessage("SQL_C_DATE");
110 if (DataTypeSupported(pDb
,SQL_C_DEFAULT
))
111 wxLogMessage("SQL_C_DEFAULT");
114 if (DataTypeSupported(pDb
,SQL_C_DOUBLE
))
115 wxLogMessage("SQL_C_DOUBLE");
118 if (DataTypeSupported(pDb
,SQL_C_FLOAT
))
119 wxLogMessage("SQL_C_FLOAT");
122 if (DataTypeSupported(pDb
,SQL_C_GUID
))
123 wxLogMessage("SQL_C_GUID");
125 #ifdef SQL_C_INTERVAL_DAY
126 if (DataTypeSupported(pDb
,SQL_C_INTERVAL_DAY
))
127 wxLogMessage("SQL_C_INTERVAL_DAY");
129 #ifdef SQL_C_INTERVAL_DAY_TO_HOUR
130 if (DataTypeSupported(pDb
,SQL_C_INTERVAL_DAY_TO_HOUR
))
131 wxLogMessage("SQL_C_INTERVAL_DAY_TO_HOUR");
133 #ifdef SQL_C_INTERVAL_DAY_TO_MINUTE
134 if (DataTypeSupported(pDb
,SQL_C_INTERVAL_DAY_TO_MINUTE
))
135 wxLogMessage("SQL_C_INTERVAL_DAY_TO_MINUTE");
137 #ifdef SQL_C_INTERVAL_DAY_TO_SECOND
138 if (DataTypeSupported(pDb
,SQL_C_INTERVAL_DAY_TO_SECOND
))
139 wxLogMessage("SQL_C_INTERVAL_DAY_TO_SECOND");
141 #ifdef SQL_C_INTERVAL_HOUR
142 if (DataTypeSupported(pDb
,SQL_C_INTERVAL_HOUR
))
143 wxLogMessage("SQL_C_INTERVAL_HOUR");
145 #ifdef SQL_C_INTERVAL_HOUR_TO_MINUTE
146 if (DataTypeSupported(pDb
,SQL_C_INTERVAL_HOUR_TO_MINUTE
))
147 wxLogMessage("SQL_C_INTERVAL_HOUR_TO_MINUTE");
149 #ifdef SQL_C_INTERVAL_HOUR_TO_SECOND
150 if (DataTypeSupported(pDb
,SQL_C_INTERVAL_HOUR_TO_SECOND
))
151 wxLogMessage("SQL_C_INTERVAL_HOUR_TO_SECOND");
153 #ifdef SQL_C_INTERVAL_MINUTE
154 if (DataTypeSupported(pDb
,SQL_C_INTERVAL_MINUTE
))
155 wxLogMessage("SQL_C_INTERVAL_MINUTE");
157 #ifdef SQL_C_INTERVAL_MINUTE_TO_SECOND
158 if (DataTypeSupported(pDb
,SQL_C_INTERVAL_MINUTE_TO_SECOND
))
159 wxLogMessage("SQL_C_INTERVAL_MINUTE_TO_SECOND");
161 #ifdef SQL_C_INTERVAL_MONTH
162 if (DataTypeSupported(pDb
,SQL_C_INTERVAL_MONTH
))
163 wxLogMessage("SQL_C_INTERVAL_MONTH");
165 #ifdef SQL_C_INTERVAL_SECOND
166 if (DataTypeSupported(pDb
,SQL_C_INTERVAL_SECOND
))
167 wxLogMessage("SQL_C_INTERVAL_SECOND");
169 #ifdef SQL_C_INTERVAL_YEAR
170 if (DataTypeSupported(pDb
,SQL_C_INTERVAL_YEAR
))
171 wxLogMessage("SQL_C_INTERVAL_YEAR");
173 #ifdef SQL_C_INTERVAL_YEAR_TO_MONTH
174 if (DataTypeSupported(pDb
,SQL_C_INTERVAL_YEAR_TO_MONTH
))
175 wxLogMessage("SQL_C_INTERVAL_YEAR_TO_MONTH");
178 if (DataTypeSupported(pDb
,SQL_C_LONG
))
179 wxLogMessage("SQL_C_LONG");
182 if (DataTypeSupported(pDb
,SQL_C_NUMERIC
))
183 wxLogMessage("SQL_C_NUMERIC");
186 if (DataTypeSupported(pDb
,SQL_C_SBIGINT
))
187 wxLogMessage("SQL_C_SBIGINT");
190 if (DataTypeSupported(pDb
,SQL_C_SHORT
))
191 wxLogMessage("SQL_C_SHORT");
194 if (DataTypeSupported(pDb
,SQL_C_SLONG
))
195 wxLogMessage("SQL_C_SLONG");
198 if (DataTypeSupported(pDb
,SQL_C_SSHORT
))
199 wxLogMessage("SQL_C_SSHORT");
201 #ifdef SQL_C_STINYINT
202 if (DataTypeSupported(pDb
,SQL_C_STINYINT
))
203 wxLogMessage("SQL_C_STINYINT");
206 if (DataTypeSupported(pDb
,SQL_C_TIME
))
207 wxLogMessage("SQL_C_TIME");
209 #ifdef SQL_C_TIMESTAMP
210 if (DataTypeSupported(pDb
,SQL_C_TIMESTAMP
))
211 wxLogMessage("SQL_C_TIMESTAMP");
214 if (DataTypeSupported(pDb
,SQL_C_TINYINT
))
215 wxLogMessage("SQL_C_TINYINT");
217 #ifdef SQL_C_TYPE_DATE
218 if (DataTypeSupported(pDb
,SQL_C_TYPE_DATE
))
219 wxLogMessage("SQL_C_TYPE_DATE");
221 #ifdef SQL_C_TYPE_TIME
222 if (DataTypeSupported(pDb
,SQL_C_TYPE_TIME
))
223 wxLogMessage("SQL_C_TYPE_TIME");
225 #ifdef SQL_C_TYPE_TIMESTAMP
226 if (DataTypeSupported(pDb
,SQL_C_TYPE_TIMESTAMP
))
227 wxLogMessage("SQL_C_TYPE_TIMESTAMP");
230 if (DataTypeSupported(pDb
,SQL_C_UBIGINT
))
231 wxLogMessage("SQL_C_UBIGINT");
234 if (DataTypeSupported(pDb
,SQL_C_ULONG
))
235 wxLogMessage("SQL_C_ULONG");
238 if (DataTypeSupported(pDb
,SQL_C_USHORT
))
239 wxLogMessage("SQL_C_USHORT");
241 #ifdef SQL_C_UTINYINT
242 if (DataTypeSupported(pDb
,SQL_C_UTINYINT
))
243 wxLogMessage("SQL_C_UTINYINT");
245 #ifdef SQL_C_VARBOOKMARK
246 if (DataTypeSupported(pDb
,SQL_C_VARBOOKMARK
))
247 wxLogMessage("SQL_C_VARBOOKMARK");
250 // Extended SQL types
252 if (DataTypeSupported(pDb
,SQL_DATE
))
253 wxLogMessage("SQL_DATE");
256 if (DataTypeSupported(pDb
,SQL_INTERVAL
))
257 wxLogMessage("SQL_INTERVAL");
260 if (DataTypeSupported(pDb
,SQL_TIME
))
261 wxLogMessage("SQL_TIME");
264 if (DataTypeSupported(pDb
,SQL_TIMESTAMP
))
265 wxLogMessage("SQL_TIMESTAMP");
267 #ifdef SQL_LONGVARCHAR
268 if (DataTypeSupported(pDb
,SQL_LONGVARCHAR
))
269 wxLogMessage("SQL_LONGVARCHAR");
272 if (DataTypeSupported(pDb
,SQL_BINARY
))
273 wxLogMessage("SQL_BINARY");
276 if (DataTypeSupported(pDb
,SQL_VARBINARY
))
277 wxLogMessage("SQL_VARBINARY");
279 #ifdef SQL_LONGVARBINARY
280 if (DataTypeSupported(pDb
,SQL_LONGVARBINARY
))
281 wxLogMessage("SQL_LONGVARBINARY");
284 if (DataTypeSupported(pDb
,SQL_BIGINT
))
285 wxLogMessage("SQL_BIGINT");
288 if (DataTypeSupported(pDb
,SQL_TINYINT
))
289 wxLogMessage("SQL_TINYINT");
292 if (DataTypeSupported(pDb
,SQL_BIT
))
293 wxLogMessage("SQL_BIT");
296 if (DataTypeSupported(pDb
,SQL_GUID
))
297 wxLogMessage("SQL_GUID");
301 if (DataTypeSupported(pDb
,SQL_CHAR
))
302 wxLogMessage("SQL_CHAR");
305 if (DataTypeSupported(pDb
,SQL_INTEGER
))
306 wxLogMessage("SQL_INTEGER");
309 if (DataTypeSupported(pDb
,SQL_SMALLINT
))
310 wxLogMessage("SQL_SMALLINT");
313 if (DataTypeSupported(pDb
,SQL_REAL
))
314 wxLogMessage("SQL_REAL");
317 if (DataTypeSupported(pDb
,SQL_DOUBLE
))
318 wxLogMessage("SQL_DOUBLE");
321 if (DataTypeSupported(pDb
,SQL_NUMERIC
))
322 wxLogMessage("SQL_NUMERIC");
325 if (DataTypeSupported(pDb
,SQL_DATE
))
326 wxLogMessage("SQL_DATE");
329 if (DataTypeSupported(pDb
,SQL_TIME
))
330 wxLogMessage("SQL_TIME");
333 if (DataTypeSupported(pDb
,SQL_TIMESTAMP
))
334 wxLogMessage("SQL_TIMESTAMP");
337 if (DataTypeSupported(pDb
,SQL_VARCHAR
))
338 wxLogMessage("SQL_VARCHAR");
343 if (DataTypeSupported(pDb
,SQL_C_TCHAR
))
344 wxLogMessage("SQL_C_TCHAR (Unicode support is possible)");
348 } // CheckSupportForAllDataTypes()
351 bool DatabaseDemoApp::OnInit()
356 // Create the main frame window
357 DemoFrame
= new DatabaseDemoFrame(NULL
, wxT("wxWindows Database Demo"), wxPoint(50, 50), wxSize(537, 480));
360 DemoFrame
->SetIcon(wxICON(db
));
363 wxMenu
*file_menu
= new wxMenu
;
364 file_menu
->Append(FILE_CREATE
, wxT("&Create CONTACT table"));
365 file_menu
->Append(FILE_RECREATE_TABLE
, wxT("&Recreate CONTACT table"));
366 file_menu
->Append(FILE_RECREATE_INDEXES
, wxT("&Recreate CONTACT indexes"));
368 file_menu
->Append(FILE_DBGRID_TABLE
, wxT("&Open DB Grid example"));
370 file_menu
->Append(FILE_EXIT
, wxT("E&xit"));
372 wxMenu
*edit_menu
= new wxMenu
;
373 edit_menu
->Append(EDIT_PARAMETERS
, wxT("&Parameters..."));
375 wxMenu
*help_menu
= new wxMenu
;
376 help_menu
->Append(HELP_ABOUT
, wxT("&About"));
378 wxMenuBar
*menu_bar
= new wxMenuBar
;
379 menu_bar
->Append(file_menu
, wxT("&File"));
380 menu_bar
->Append(edit_menu
, wxT("&Edit"));
381 menu_bar
->Append(help_menu
, wxT("&Help"));
382 DemoFrame
->SetMenuBar(menu_bar
);
384 params
.ODBCSource
[0] = 0;
385 params
.UserName
[0] = 0;
386 params
.Password
[0] = 0;
387 params
.DirPath
[0] = 0;
390 DemoFrame
->Show(TRUE
);
392 // Passing NULL for the SQL environment handle causes
393 // the wxDbConnectInf constructor to obtain a handle
396 // WARNING: Be certain that you do not free this handle
397 // directly with SQLFreeEnv(). Use either the
398 // method ::FreeHenv() or delete the DbConnectInf.
399 DbConnectInf
= new wxDbConnectInf(NULL
, params
.ODBCSource
, params
.UserName
,
400 params
.Password
, params
.DirPath
);
402 if (!DbConnectInf
|| !DbConnectInf
->GetHenv())
404 wxMessageBox(wxT("Unable to define data source connection info."), wxT("DB CONNECTION ERROR..."),wxOK
| wxICON_EXCLAMATION
);
405 wxDELETE(DbConnectInf
);
408 if (!ReadParamFile(params
))
409 DemoFrame
->BuildParameterDialog(NULL
);
411 if (!wxStrlen(params
.ODBCSource
))
413 wxDELETE(DbConnectInf
);
417 DbConnectInf
->SetDsn(params
.ODBCSource
);
418 DbConnectInf
->SetUserID(params
.UserName
);
419 DbConnectInf
->SetPassword(params
.Password
);
420 DbConnectInf
->SetDefaultDir(params
.DirPath
);
422 READONLY_DB
= wxDbGetConnection(DbConnectInf
);
423 if (READONLY_DB
== 0)
425 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
);
426 DemoFrame
->BuildParameterDialog(NULL
);
427 wxDELETE(DbConnectInf
);
428 wxMessageBox(wxT("Now exiting program.\n\nRestart program to try any new settings."),wxT("Notice..."),wxOK
| wxICON_INFORMATION
);
432 DemoFrame
->BuildEditorDialog();
435 DemoFrame
->Refresh();
438 } // DatabaseDemoApp::OnInit()
442 * Remove CR or CR/LF from a character string.
444 char* wxRemoveLineTerminator(char* aString
)
446 int len
= strlen(aString
);
447 while (len
> 0 && (aString
[len
-1] == '\r' || aString
[len
-1] == '\n')) {
448 aString
[len
-1] = '\0';
455 bool DatabaseDemoApp::ReadParamFile(Cparameters
¶ms
)
458 if ((paramFile
= fopen(PARAM_FILENAME
, wxT("r"))) == NULL
)
461 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
);
462 wxMessageBox(tStr
,wxT("File I/O Error..."),wxOK
| wxICON_EXCLAMATION
);
467 wxChar buffer
[1000+1];
468 fgets(buffer
, sizeof(params
.ODBCSource
), paramFile
);
469 wxRemoveLineTerminator(buffer
);
470 wxStrcpy(params
.ODBCSource
,buffer
);
472 fgets(buffer
, sizeof(params
.UserName
), paramFile
);
473 wxRemoveLineTerminator(buffer
);
474 wxStrcpy(params
.UserName
,buffer
);
476 fgets(buffer
, sizeof(params
.Password
), paramFile
);
477 wxRemoveLineTerminator(buffer
);
478 wxStrcpy(params
.Password
,buffer
);
480 fgets(buffer
, sizeof(params
.DirPath
), paramFile
);
481 wxRemoveLineTerminator(buffer
);
482 wxStrcpy(params
.DirPath
,buffer
);
487 } // DatabaseDemoApp::ReadParamFile()
490 bool DatabaseDemoApp::WriteParamFile(Cparameters
¶ms
)
493 if ((paramFile
= fopen(PARAM_FILENAME
, wxT("wt"))) == NULL
)
496 tStr
.Printf(wxT("Unable to write/overwrite '%s'."),PARAM_FILENAME
);
497 wxMessageBox(tStr
,wxT("File I/O Error..."),wxOK
| wxICON_EXCLAMATION
);
501 fputs(wxGetApp().params
.ODBCSource
, paramFile
);
502 fputc(wxT('\n'), paramFile
);
503 fputs(wxGetApp().params
.UserName
, paramFile
);
504 fputc(wxT('\n'), paramFile
);
505 fputs(wxGetApp().params
.Password
, paramFile
);
506 fputc(wxT('\n'), paramFile
);
507 fputs(wxGetApp().params
.DirPath
, paramFile
);
508 fputc(wxT('\n'), paramFile
);
512 } // DatabaseDemoApp::WriteParamFile()
515 void DatabaseDemoApp::CreateDataTable(bool recreate
)
519 Ok
= (wxMessageBox(wxT("Any data currently residing in the table will be erased.\n\nAre you sure?"),wxT("Confirm"),wxYES_NO
|wxICON_QUESTION
) == wxYES
);
528 Contact
->GetDb()->RollbackTrans(); // Make sure the current cursor is in a known/stable state
530 if (!Contact
->CreateTable(recreate
))
534 tStr
= wxT("Error creating CONTACTS table.\nTable was not created.\n\n");
535 wxMessageBox(wxDbLogExtendedErrorMsg(tStr
.c_str(),Contact
->GetDb(),__FILE__
,__LINE__
),
536 wxT("ODBC Error..."),wxOK
| wxICON_EXCLAMATION
);
542 if (!Contact
->CreateIndexes(recreate
))
546 tStr
= wxT("Error creating CONTACTS indexes.\nIndexes will be unavailable.\n\n");
547 wxMessageBox(wxDbLogExtendedErrorMsg(tStr
.c_str(),Contact
->GetDb(),__FILE__
,__LINE__
),
548 wxT("ODBC Error..."),wxOK
| wxICON_EXCLAMATION
);
557 wxMessageBox(wxT("Table and index(es) were successfully created."),wxT("Notice..."),wxOK
| wxICON_INFORMATION
);
558 } // DatabaseDemoApp::CreateDataTable()
561 BEGIN_EVENT_TABLE(DatabaseDemoFrame
, wxFrame
)
562 EVT_MENU(FILE_CREATE
, DatabaseDemoFrame::OnCreate
)
563 EVT_MENU(FILE_RECREATE_TABLE
, DatabaseDemoFrame::OnRecreateTable
)
564 EVT_MENU(FILE_RECREATE_INDEXES
, DatabaseDemoFrame::OnRecreateIndexes
)
566 EVT_MENU(FILE_DBGRID_TABLE
, DatabaseDemoFrame::OnDbGridTable
)
568 EVT_MENU(FILE_EXIT
, DatabaseDemoFrame::OnExit
)
569 EVT_MENU(EDIT_PARAMETERS
, DatabaseDemoFrame::OnEditParameters
)
570 EVT_MENU(HELP_ABOUT
, DatabaseDemoFrame::OnAbout
)
571 EVT_CLOSE(DatabaseDemoFrame::OnCloseWindow
)
575 // DatabaseDemoFrame constructor
576 DatabaseDemoFrame::DatabaseDemoFrame(wxFrame
*frame
, const wxString
& title
,
577 const wxPoint
& pos
, const wxSize
& size
):
578 wxFrame(frame
, -1, title
, pos
, size
)
580 // Put any code in necessary for initializing the main frame here
584 delete wxLog::SetActiveTarget(new wxLogStderr
);
586 } // DatabaseDemoFrame constructor
588 DatabaseDemoFrame::~DatabaseDemoFrame()
590 delete wxLog::SetActiveTarget(NULL
);
591 } // DatabaseDemoFrame destructor
594 void DatabaseDemoFrame::OnCreate(wxCommandEvent
& event
)
596 wxGetApp().CreateDataTable(FALSE
);
597 } // DatabaseDemoFrame::OnCreate()
600 void DatabaseDemoFrame::OnRecreateTable(wxCommandEvent
& event
)
602 wxGetApp().CreateDataTable(TRUE
);
603 } // DatabaseDemoFrame::OnRecreate()
606 void DatabaseDemoFrame::OnRecreateIndexes(wxCommandEvent
& event
)
608 wxGetApp().Contact
->GetDb()->RollbackTrans(); // Make sure the current cursor is in a known/stable state
610 if (!wxGetApp().Contact
->CreateIndexes(TRUE
))
615 tStr
= wxT("Error creating CONTACTS indexes.\nNew indexes will be unavailable.\n\n");
616 wxMessageBox(wxDbLogExtendedErrorMsg(tStr
.c_str(),wxGetApp().Contact
->GetDb(),__FILE__
,__LINE__
),
617 wxT("ODBC Error..."),wxOK
| wxICON_EXCLAMATION
);
621 wxMessageBox(wxT("Index(es) were successfully recreated."),wxT("Notice..."),wxOK
| wxICON_INFORMATION
);
623 } // DatabaseDemoFrame::OnRecreateIndexes()
627 void DatabaseDemoFrame::OnDbGridTable(wxCommandEvent
& )
629 DbGridFrame
*frame
= new DbGridFrame(this);
630 if (frame
->Initialize())
637 void DatabaseDemoFrame::OnExit(wxCommandEvent
& event
)
640 } // DatabaseDemoFrame::OnExit()
643 void DatabaseDemoFrame::OnEditParameters(wxCommandEvent
& event
)
645 if ((pEditorDlg
->mode
!= mCreate
) && (pEditorDlg
->mode
!= mEdit
))
646 BuildParameterDialog(this);
648 wxMessageBox(wxT("Cannot change database parameters while creating or editing a record"),wxT("Notice..."),wxOK
| wxICON_INFORMATION
);
649 } // DatabaseDemoFrame::OnEditParameters()
652 void DatabaseDemoFrame::OnAbout(wxCommandEvent
& event
)
654 wxMessageBox(wxT("wxWindows sample program for database classes\n\nContributed on 27 July 1998"),wxT("About..."),wxOK
| wxICON_INFORMATION
);
655 } // DatabaseDemoFrame::OnAbout()
658 // Put any additional checking necessary to make certain it is alright
659 // to close the program here that is not done elsewhere
660 void DatabaseDemoFrame::OnCloseWindow(wxCloseEvent
& event
)
663 if (pEditorDlg
&& pEditorDlg
->Close())
674 wxDELETE(wxGetApp().Contact
);
676 // This function will close all the connections to the database that have been
677 // previously cached.
678 wxDbCloseConnections();
680 // Deletion of the wxDbConnectInf instance must be the LAST thing done that
681 // has anything to do with the database. Deleting this before disconnecting,
682 // freeing/closing connections, etc will result in a crash!
683 wxDELETE(wxGetApp().DbConnectInf
);
687 } // DatabaseDemoFrame::OnCloseWindow()
690 void DatabaseDemoFrame::BuildEditorDialog()
693 pEditorDlg
= new CeditorDlg(this);
696 pEditorDlg
->Initialize();
697 if (!pEditorDlg
->initialized
)
701 wxMessageBox(wxT("Unable to initialize the editor dialog for some reason"),wxT("Error..."),wxOK
| wxICON_EXCLAMATION
);
707 wxMessageBox(wxT("Unable to create the editor dialog for some reason"),wxT("Error..."),wxOK
| wxICON_EXCLAMATION
);
710 } // DatabaseDemoFrame::BuildEditorDialog()
713 void DatabaseDemoFrame::BuildParameterDialog(wxWindow
*parent
)
715 pParamDlg
= new CparameterDlg(parent
);
718 wxMessageBox(wxT("Unable to create the parameter dialog for some reason"),wxT("Error..."),wxOK
| wxICON_EXCLAMATION
);
719 } // DatabaseDemoFrame::BuildParameterDialog()
723 * Constructor note: If no wxDb object is passed in, a new connection to the database
724 * is created for this instance of Ccontact. This can be a slow process depending
725 * on the database engine being used, and some database engines have a limit on the
726 * number of connections (either hard limits, or license restricted) so care should
727 * be used to use as few connections as is necessary.
729 * IMPORTANT: Objects which share a wxDb pointer are ALL acted upon whenever a member
730 * function of pDb is called (i.e. CommitTrans() or RollbackTrans(), so if modifying
731 * or creating a table objects which use the same pDb, know that all the objects
732 * will be committed or rolled back when any of the objects has this function call made.
734 Ccontact::Ccontact (wxDb
*pwxDb
) : wxDbTable(pwxDb
? pwxDb
: wxDbGetConnection(wxGetApp().DbConnectInf
),
735 CONTACT_TABLE_NAME
, CONTACT_NO_COLS
, wxT(""),
736 !wxDB_QUERY_ONLY
, wxGetApp().DbConnectInf
->GetDefaultDir())
738 // This is used to represent whether the database connection should be released
739 // when this instance of the object is deleted. If using the same connection
740 // for multiple instance of database objects, then the connection should only be
741 // released when the last database instance using the connection is deleted
745 GetDb()->SetSqlLogging(sqlLogON
);
749 } // Ccontact Constructor
752 void Ccontact::Initialize()
761 JoinDate
.year
= 1980;
767 JoinDate
.fraction
= 0;
768 NativeLanguage
= langENGLISH
;
772 } // Ccontact::Initialize
775 Ccontact::~Ccontact()
779 if (!wxDbFreeConnection(GetDb()))
782 tStr
= wxT("Unable to Free the Ccontact data table handle\n\n");
784 wxMessageBox(wxDbLogExtendedErrorMsg(tStr
.c_str(),wxGetApp().Contact
->GetDb(),__FILE__
,__LINE__
),
785 wxT("ODBC Error..."),wxOK
| wxICON_EXCLAMATION
);
788 } // Ccontract destructor
792 * Handles setting up all the connections for the interface from the wxDbTable
793 * functions to interface to the data structure used to store records in
794 * memory, and for all the column definitions that define the table structure
796 void Ccontact::SetupColumns()
798 // NOTE: Columns now are 8 character names, as that is all dBase can support. Longer
799 // names can be used for other database engines
800 SetColDefs ( 0,wxT("NAME"), DB_DATA_TYPE_VARCHAR
, Name
, SQL_C_CHAR
, sizeof(Name
), TRUE
, TRUE
); // Primary index
801 SetColDefs ( 1,wxT("ADDRESS1"), DB_DATA_TYPE_VARCHAR
, Addr1
, SQL_C_CHAR
, sizeof(Addr1
), FALSE
,TRUE
);
802 SetColDefs ( 2,wxT("ADDRESS2"), DB_DATA_TYPE_VARCHAR
, Addr2
, SQL_C_CHAR
, sizeof(Addr2
), FALSE
,TRUE
);
803 SetColDefs ( 3,wxT("CITY"), DB_DATA_TYPE_VARCHAR
, City
, SQL_C_CHAR
, sizeof(City
), FALSE
,TRUE
);
804 SetColDefs ( 4,wxT("STATE"), DB_DATA_TYPE_VARCHAR
, State
, SQL_C_CHAR
, sizeof(State
), FALSE
,TRUE
);
805 SetColDefs ( 5,wxT("POSTCODE"), DB_DATA_TYPE_VARCHAR
, PostalCode
, SQL_C_CHAR
, sizeof(PostalCode
), FALSE
,TRUE
);
806 SetColDefs ( 6,wxT("COUNTRY"), DB_DATA_TYPE_VARCHAR
, Country
, SQL_C_CHAR
, sizeof(Country
), FALSE
,TRUE
);
807 SetColDefs ( 7,wxT("JOINDATE"), DB_DATA_TYPE_DATE
, &JoinDate
, SQL_C_TIMESTAMP
, sizeof(JoinDate
), FALSE
,TRUE
);
808 SetColDefs ( 8,wxT("IS_DEV"), DB_DATA_TYPE_INTEGER
, &IsDeveloper
, SQL_C_BOOLEAN(IsDeveloper
), sizeof(IsDeveloper
), FALSE
,TRUE
);
809 SetColDefs ( 9,wxT("CONTRIBS"), DB_DATA_TYPE_INTEGER
, &Contributions
, SQL_C_UTINYINT
, sizeof(Contributions
), FALSE
,TRUE
);
810 SetColDefs (10,wxT("LINE_CNT"), DB_DATA_TYPE_INTEGER
, &LinesOfCode
, SQL_C_ULONG
, sizeof(LinesOfCode
), FALSE
,TRUE
);
811 SetColDefs (11,wxT("LANGUAGE"), DB_DATA_TYPE_INTEGER
, &NativeLanguage
, SQL_C_ENUM
, sizeof(NativeLanguage
), FALSE
,TRUE
);
812 #if wxODBC_BLOB_EXPERIMENT > 0
813 SetColDefs (12,wxT("PICTURE"), DB_DATA_TYPE_BLOB
, Picture
, SQL_LONGVARBINARY
, sizeof(Picture
), FALSE
,TRUE
);
815 } // Ccontact::SetupColumns
818 bool Ccontact::CreateIndexes(bool recreate
)
820 // This index could easily be accomplished with an "orderBy" clause,
821 // but is done to show how to construct a non-primary index.
823 wxDbIdxDef idxDef
[2];
827 wxStrcpy(idxDef
[0].ColName
, "IS_DEV");
828 idxDef
[0].Ascending
= TRUE
;
830 wxStrcpy(idxDef
[1].ColName
, "NAME");
831 idxDef
[1].Ascending
= TRUE
;
833 indexName
= GetTableName();
834 indexName
+= "_IDX1";
835 Ok
= CreateIndex(indexName
.c_str(), TRUE
, 2, idxDef
, recreate
);
838 } // Ccontact::CreateIndexes()
842 * Having a function to do a query on the primary key (and possibly others) is
843 * very efficient and tighter coding so that it is available where ever the object
844 * is. Great for use with multiple tables when not using views or outer joins
846 bool Ccontact::FetchByName(const wxString
&name
)
848 whereStr
.Printf(wxT("NAME = '%s'"),name
.c_str());
849 SetWhereClause(whereStr
.c_str());
850 SetOrderByClause(wxT(""));
858 } // Ccontact::FetchByName()
863 * ************* DIALOGS ***************
868 /* CeditorDlg constructor
870 * Creates the dialog used for creating/editing/deleting/copying a Ccontact object.
871 * This dialog actually is drawn in the main frame of the program
873 * An instance of Ccontact is created - "Contact" - which is used to hold the Ccontact
874 * object that is currently being worked with.
877 BEGIN_EVENT_TABLE(CeditorDlg
, wxPanel
)
878 EVT_BUTTON(-1, CeditorDlg::OnButton
)
879 EVT_CLOSE(CeditorDlg::OnCloseWindow
)
882 CeditorDlg::CeditorDlg(wxWindow
*parent
) : wxPanel (parent
, 0, 0, 537, 480)
884 // Since the ::OnCommand() function is overridden, this prevents the widget
885 // detection in ::OnCommand() until all widgets have been initialized to prevent
886 // uninitialized pointers from crashing the program
887 widgetPtrsSet
= FALSE
;
894 } // CeditorDlg constructor
897 void CeditorDlg::OnCloseWindow(wxCloseEvent
& event
)
900 if ((mode
!= mCreate
) && (mode
!= mEdit
))
906 wxMessageBox(wxT("Must finish processing the current record being created/modified before exiting"),wxT("Notice..."),wxOK
| wxICON_INFORMATION
);
909 } // CeditorDlg::OnCloseWindow()
912 void CeditorDlg::OnButton(wxCommandEvent
&event
)
914 wxWindow
*win
= (wxWindow
*) event
.GetEventObject();
915 OnCommand( *win
, event
);
916 } // CeditorDlg::OnButton()
919 void CeditorDlg::OnCommand(wxWindow
& win
, wxCommandEvent
& event
)
923 widgetName
= win
.GetName();
928 if (widgetName
== pCreateBtn
->GetName())
930 wxGetApp().Contact
->Initialize();
933 pNameTxt
->SetValue(wxT(""));
934 pNameTxt
->SetFocus();
938 if (widgetName
== pEditBtn
->GetName())
940 saveName
= wxGetApp().Contact
->Name
;
942 pNameTxt
->SetFocus();
946 if (widgetName
== pCopyBtn
->GetName())
949 pNameTxt
->SetValue(wxT(""));
950 pNameTxt
->SetFocus();
954 if (widgetName
== pDeleteBtn
->GetName())
956 bool Ok
= (wxMessageBox(wxT("Are you sure?"),wxT("Confirm"),wxYES_NO
|wxICON_QUESTION
) == wxYES
);
961 if (Ok
&& wxGetApp().Contact
->Delete())
963 // NOTE: Deletions are not finalized until a CommitTrans() is performed.
964 // If the commit were not performed, the program will continue to
965 // show the table contents as if they were deleted until this instance
966 // of Ccontact is deleted. If the Commit wasn't performed, the
967 // database will automatically Rollback the changes when the database
968 // connection is terminated
969 wxGetApp().Contact
->GetDb()->CommitTrans();
971 // Try to get the row that followed the just deleted row in the orderBy sequence
974 // There was now row (in sequence) after the just deleted row, so get the
975 // row which preceded the just deleted row
978 // There are now no rows remaining, so clear the dialog widgets
979 wxGetApp().Contact
->Initialize();
983 SetMode(mode
); // force reset of button enable/disable
987 wxGetApp().Contact
->GetDb()->RollbackTrans();
993 if (widgetName
== pSaveBtn
->GetName())
999 if (widgetName
== pCancelBtn
->GetName())
1001 bool Ok
= (wxMessageBox(wxT("Are you sure?"),wxT("Confirm"),wxYES_NO
|wxICON_QUESTION
) == wxYES
);
1006 if (saveName
.IsEmpty())
1008 wxGetApp().Contact
->Initialize();
1015 // Requery previous record
1016 if (wxGetApp().Contact
->FetchByName(saveName
))
1024 // Previous record not available, retrieve first record in table
1025 if (wxGetApp().Contact
->GetDb()->Dbms() != dbmsPOSTGRES
&&
1026 wxGetApp().Contact
->GetDb()->Dbms() != dbmsMY_SQL
)
1028 wxGetApp().Contact
->whereStr
= wxT("NAME = (SELECT MIN(NAME) FROM ");
1029 wxGetApp().Contact
->whereStr
+= wxGetApp().Contact
->GetTableName();
1030 wxGetApp().Contact
->whereStr
+= wxT(")");
1031 wxGetApp().Contact
->SetWhereClause(wxGetApp().Contact
->whereStr
.c_str());
1034 wxGetApp().Contact
->SetWhereClause(wxT(""));
1036 if (!wxGetApp().Contact
->Query())
1039 tStr
= wxT("ODBC error during Query()\n\n");
1040 wxMessageBox(wxDbLogExtendedErrorMsg(tStr
.c_str(),wxGetApp().Contact
->GetDb(),__FILE__
,__LINE__
),
1041 wxT("ODBC Error..."),wxOK
| wxICON_EXCLAMATION
);
1046 if (wxGetApp().Contact
->GetNext()) // Successfully read first record
1052 // No contacts are available, clear dialog
1053 wxGetApp().Contact
->Initialize();
1059 if (widgetName
== pPrevBtn
->GetName())
1066 if (widgetName
== pNextBtn
->GetName())
1073 if (widgetName
== pQueryBtn
->GetName())
1075 // Display the query dialog box
1076 wxChar qryWhere
[DB_MAX_WHERE_CLAUSE_LEN
+1];
1077 wxStrcpy(qryWhere
, (const wxChar
*) wxGetApp().Contact
->qryWhereStr
);
1078 wxChar
*tblName
[] = {(wxChar
*)CONTACT_TABLE_NAME
, 0};
1079 new CqueryDlg(GetParent(), wxGetApp().Contact
->GetDb(), tblName
, qryWhere
);
1081 // Query the first record in the new record set and
1082 // display it, if the query string has changed.
1083 if (wxStrcmp(qryWhere
, (const wxChar
*) wxGetApp().Contact
->qryWhereStr
))
1085 wxGetApp().Contact
->whereStr
.Empty();
1086 wxGetApp().Contact
->SetOrderByClause("NAME");
1088 if (wxGetApp().Contact
->GetDb()->Dbms() != dbmsPOSTGRES
&&
1089 wxGetApp().Contact
->GetDb()->Dbms() != dbmsMY_SQL
)
1091 wxGetApp().Contact
->whereStr
= wxT("NAME = (SELECT MIN(NAME) FROM ");
1092 wxGetApp().Contact
->whereStr
+= CONTACT_TABLE_NAME
;
1095 // Append the query where string (if there is one)
1096 wxGetApp().Contact
->qryWhereStr
= qryWhere
;
1097 if (wxStrlen(qryWhere
))
1099 wxGetApp().Contact
->whereStr
+= wxT(" WHERE ");
1100 wxGetApp().Contact
->whereStr
+= wxGetApp().Contact
->qryWhereStr
;
1102 // Close the expression with a right paren
1103 wxGetApp().Contact
->whereStr
+= wxT(")");
1104 // Requery the table
1105 wxGetApp().Contact
->SetWhereClause(wxGetApp().Contact
->whereStr
.c_str());
1106 if (!wxGetApp().Contact
->Query())
1109 tStr
= wxT("ODBC error during Query()\n\n");
1110 wxMessageBox(wxDbLogExtendedErrorMsg(tStr
.c_str(),wxGetApp().Contact
->GetDb(),__FILE__
,__LINE__
),
1111 wxT("ODBC Error..."),wxOK
| wxICON_EXCLAMATION
);
1115 // Display the first record from the query set
1116 if (!wxGetApp().Contact
->GetNext())
1117 wxGetApp().Contact
->Initialize();
1121 // Enable/Disable the reset button
1122 pResetBtn
->Enable(!wxGetApp().Contact
->qryWhereStr
.IsEmpty());
1128 if (widgetName
== pResetBtn
->GetName())
1130 // Clear the additional where criteria established by the query feature
1131 wxGetApp().Contact
->qryWhereStr
= wxT("");
1132 wxGetApp().Contact
->SetOrderByClause(wxT("NAME"));
1134 if (wxGetApp().Contact
->GetDb()->Dbms() != dbmsPOSTGRES
&&
1135 wxGetApp().Contact
->GetDb()->Dbms() != dbmsMY_SQL
)
1137 wxGetApp().Contact
->whereStr
= wxT("NAME = (SELECT MIN(NAME) FROM ");
1138 wxGetApp().Contact
->whereStr
+= CONTACT_TABLE_NAME
;
1139 wxGetApp().Contact
->whereStr
+= wxT(")");
1142 wxGetApp().Contact
->SetWhereClause(wxGetApp().Contact
->whereStr
.c_str());
1143 if (!wxGetApp().Contact
->Query())
1146 tStr
= wxT("ODBC error during Query()\n\n");
1147 wxMessageBox(wxDbLogExtendedErrorMsg(tStr
.c_str(),wxGetApp().Contact
->GetDb(),__FILE__
,__LINE__
),
1148 wxT("ODBC Error..."),wxOK
| wxICON_EXCLAMATION
);
1151 if (!wxGetApp().Contact
->GetNext())
1152 wxGetApp().Contact
->Initialize();
1154 pResetBtn
->Enable(FALSE
);
1160 if (widgetName
== pNameListBtn
->GetName())
1162 new ClookUpDlg(/* wxWindow *parent */ this,
1163 /* wxChar *windowTitle */ wxT("Select contact name"),
1164 /* wxChar *tableName */ (wxChar
*) CONTACT_TABLE_NAME
,
1165 /* wxChar *dispCol1 */ wxT("NAME"),
1166 /* wxChar *dispCol2 */ wxT("JOINDATE"),
1167 /* wxChar *where */ wxT(""),
1168 /* wxChar *orderBy */ wxT("NAME"),
1169 /* wxDb *pDb */ wxGetApp().READONLY_DB
,
1170 /* const wxString &defDir */ wxGetApp().DbConnectInf
->GetDefaultDir(),
1171 /* bool distinctValues */ TRUE
);
1173 if (ListDB_Selection
&& wxStrlen(ListDB_Selection
))
1175 wxString w
= wxT("NAME = '");
1176 w
+= ListDB_Selection
;
1184 if (widgetName
== pDataTypesBtn
->GetName())
1186 CheckSupportForAllDataTypes(wxGetApp().READONLY_DB
);
1187 wxMessageBox("Support datatypes was dumped to stdout.");
1189 } // Data types Button
1191 if (widgetName
== pDbDiagsBtn
->GetName())
1193 DisplayDbDiagnostics(wxGetApp().READONLY_DB
);
1194 wxMessageBox("Diagnostics info was dumped to stdout.");
1198 if (widgetName
== pCatalogBtn
->GetName())
1200 if (wxGetApp().Contact
->GetDb()->Catalog("","catalog.txt"))
1201 wxMessageBox("The file 'catalog.txt' was created.");
1203 wxMessageBox("Creation of the file 'catalog.txt' was failed.");
1207 } // CeditorDlg::OnCommand()
1210 bool CeditorDlg::Initialize()
1212 // Create the data structure and a new database connection.
1213 // (As there is not a pDb being passed in the constructor, a new database
1214 // connection is created)
1215 wxGetApp().Contact
= new Ccontact();
1217 if (!wxGetApp().Contact
)
1219 wxMessageBox(wxT("Unable to instantiate an instance of Ccontact"),wxT("Error..."),wxOK
| wxICON_EXCLAMATION
);
1223 // Check if the table exists or not. If it doesn't, ask the user if they want to
1224 // create the table. Continue trying to create the table until it exists, or user aborts
1225 while (!wxGetApp().Contact
->GetDb()->TableExists((wxChar
*)CONTACT_TABLE_NAME
,
1226 wxGetApp().DbConnectInf
->GetUserID(),
1227 wxGetApp().DbConnectInf
->GetDefaultDir()))
1230 tStr
.Printf(wxT("Unable to open the table '%s'. The table may\nneed to be created.\n\nDo you wish to try to create/clear the table?\n\n"),CONTACT_TABLE_NAME
);
1231 bool createTable
= (wxMessageBox(tStr
.c_str(),wxT("Confirm"),wxYES_NO
|wxICON_QUESTION
) == wxYES
);
1239 wxGetApp().CreateDataTable(FALSE
);
1242 // Tables must be "opened" before anything other than creating/deleting table can be done
1243 if (!wxGetApp().Contact
->Open())
1245 // Table does exist, or there was some problem opening it. Currently this should
1246 // never fail, except in the case of the table not exisiting or the current
1247 // user has insufficent privileges to access the table
1249 // This code is experimenting with a new function that will hopefully be available
1250 // in the 2.4 release. This check will determine whether the open failing was due
1251 // to the table not existing, or the users privileges being insufficient to
1253 if (!wxGetApp().Contact
->GetDb()->TablePrivileges(CONTACT_TABLE_NAME
, wxT("SELECT"),
1254 wxGetApp().Contact
->GetDb()->GetUsername(),
1255 wxGetApp().Contact
->GetDb()->GetUsername(),
1256 wxGetApp().DbConnectInf
->GetDefaultDir()))
1259 tStr
.Printf(wxT("Unable to open the table '%s' (likely due to\ninsufficient privileges of the logged in user).\n\n"),CONTACT_TABLE_NAME
);
1261 wxMessageBox(wxDbLogExtendedErrorMsg(tStr
.c_str(),wxGetApp().Contact
->GetDb(),__FILE__
,__LINE__
),
1262 wxT("ODBC Error..."),wxOK
| wxICON_EXCLAMATION
);
1266 if (!wxGetApp().Contact
->GetDb()->TableExists(CONTACT_TABLE_NAME
,
1267 wxGetApp().Contact
->GetDb()->GetUsername(),
1268 wxGetApp().DbConnectInf
->GetDefaultDir()))
1271 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
);
1272 wxMessageBox(wxDbLogExtendedErrorMsg(tStr
.c_str(),wxGetApp().Contact
->GetDb(),__FILE__
,__LINE__
),
1273 wxT("ODBC Error..."),wxOK
| wxICON_EXCLAMATION
);
1281 (void)new wxStaticBox(this, EDITOR_DIALOG_FN_GROUP
, wxT(""), wxPoint(15, 1), wxSize(497, 69), 0, wxT("FunctionGrp"));
1282 (void)new wxStaticBox(this, EDITOR_DIALOG_SEARCH_GROUP
, wxT(""), wxPoint(417, 1), wxSize(95, 242), 0, wxT("SearchGrp"));
1284 pCreateBtn
= new wxButton(this, EDITOR_DIALOG_CREATE
, wxT("&Create"), wxPoint( 25, 21), wxSize( 70, 35), 0, wxDefaultValidator
, wxT("CreateBtn"));
1285 pEditBtn
= new wxButton(this, EDITOR_DIALOG_EDIT
, wxT("&Edit"), wxPoint(102, 21), wxSize( 70, 35), 0, wxDefaultValidator
, wxT("EditBtn"));
1286 pDeleteBtn
= new wxButton(this, EDITOR_DIALOG_DELETE
, wxT("&Delete"), wxPoint(179, 21), wxSize( 70, 35), 0, wxDefaultValidator
, wxT("DeleteBtn"));
1287 pCopyBtn
= new wxButton(this, EDITOR_DIALOG_COPY
, wxT("Cop&y"), wxPoint(256, 21), wxSize( 70, 35), 0, wxDefaultValidator
, wxT("CopyBtn"));
1288 pSaveBtn
= new wxButton(this, EDITOR_DIALOG_SAVE
, wxT("&Save"), wxPoint(333, 21), wxSize( 70, 35), 0, wxDefaultValidator
, wxT("SaveBtn"));
1289 pCancelBtn
= new wxButton(this, EDITOR_DIALOG_CANCEL
, wxT("C&ancel"), wxPoint(430, 21), wxSize( 70, 35), 0, wxDefaultValidator
, wxT("CancelBtn"));
1290 pPrevBtn
= new wxButton(this, EDITOR_DIALOG_PREV
, wxT("<< &Prev"), wxPoint(430, 81), wxSize( 70, 35), 0, wxDefaultValidator
, wxT("PrevBtn"));
1291 pNextBtn
= new wxButton(this, EDITOR_DIALOG_NEXT
, wxT("&Next >>"), wxPoint(430, 121), wxSize( 70, 35), 0, wxDefaultValidator
, wxT("NextBtn"));
1292 pQueryBtn
= new wxButton(this, EDITOR_DIALOG_QUERY
, wxT("&Query"), wxPoint(430, 161), wxSize( 70, 35), 0, wxDefaultValidator
, wxT("QueryBtn"));
1293 pResetBtn
= new wxButton(this, EDITOR_DIALOG_RESET
, wxT("&Reset"), wxPoint(430, 200), wxSize( 70, 35), 0, wxDefaultValidator
, wxT("ResetBtn"));
1294 pNameMsg
= new wxStaticText(this, EDITOR_DIALOG_NAME_MSG
, wxT("Name:"), wxPoint( 17, 80), wxSize( -1, -1), 0, wxT("NameMsg"));
1295 pNameTxt
= new wxTextCtrl(this, EDITOR_DIALOG_NAME_TEXT
, wxT(""), wxPoint( 17, 97), wxSize(308, 25), 0, wxDefaultValidator
, wxT("NameTxt"));
1296 pNameListBtn
= new wxButton(this, EDITOR_DIALOG_LOOKUP
, wxT("&Lookup"), wxPoint(333, 97), wxSize( 70, 24), 0, wxDefaultValidator
, wxT("LookupBtn"));
1297 pAddress1Msg
= new wxStaticText(this, EDITOR_DIALOG_ADDRESS1_MSG
, wxT("Address:"), wxPoint( 17, 130), wxSize( -1, -1), 0, wxT("Address1Msg"));
1298 pAddress1Txt
= new wxTextCtrl(this, EDITOR_DIALOG_ADDRESS2_TEXT
, wxT(""), wxPoint( 17, 147), wxSize(308, 25), 0, wxDefaultValidator
, wxT("Address1Txt"));
1299 pAddress2Msg
= new wxStaticText(this, EDITOR_DIALOG_ADDRESS2_MSG
, wxT("Address:"), wxPoint( 17, 180), wxSize( -1, -1), 0, wxT("Address2Msg"));
1300 pAddress2Txt
= new wxTextCtrl(this, EDITOR_DIALOG_ADDRESS2_TEXT
, wxT(""), wxPoint( 17, 197), wxSize(308, 25), 0, wxDefaultValidator
, wxT("Address2Txt"));
1301 pCityMsg
= new wxStaticText(this, EDITOR_DIALOG_CITY_MSG
, wxT("City:"), wxPoint( 17, 230), wxSize( -1, -1), 0, wxT("CityMsg"));
1302 pCityTxt
= new wxTextCtrl(this, EDITOR_DIALOG_CITY_TEXT
, wxT(""), wxPoint( 17, 247), wxSize(225, 25), 0, wxDefaultValidator
, wxT("CityTxt"));
1303 pStateMsg
= new wxStaticText(this, EDITOR_DIALOG_STATE_MSG
, wxT("State:"), wxPoint(250, 230), wxSize( -1, -1), 0, wxT("StateMsg"));
1304 pStateTxt
= new wxTextCtrl(this, EDITOR_DIALOG_STATE_TEXT
, wxT(""), wxPoint(250, 247), wxSize(153, 25), 0, wxDefaultValidator
, wxT("StateTxt"));
1305 pCountryMsg
= new wxStaticText(this, EDITOR_DIALOG_COUNTRY_MSG
, wxT("Country:"), wxPoint( 17, 280), wxSize( -1, -1), 0, wxT("CountryMsg"));
1306 pCountryTxt
= new wxTextCtrl(this, EDITOR_DIALOG_COUNTRY_TEXT
, wxT(""), wxPoint( 17, 297), wxSize(225, 25), 0, wxDefaultValidator
, wxT("CountryTxt"));
1307 pPostalCodeMsg
= new wxStaticText(this, EDITOR_DIALOG_POSTAL_MSG
, wxT("Postal Code:"),wxPoint(250, 280), wxSize( -1, -1), 0, wxT("PostalCodeMsg"));
1308 pPostalCodeTxt
= new wxTextCtrl(this, EDITOR_DIALOG_POSTAL_TEXT
, wxT(""), wxPoint(250, 297), wxSize(153, 25), 0, wxDefaultValidator
, wxT("PostalCodeTxt"));
1310 wxString choice_strings
[5];
1311 choice_strings
[0] = wxT("English");
1312 choice_strings
[1] = wxT("French");
1313 choice_strings
[2] = wxT("German");
1314 choice_strings
[3] = wxT("Spanish");
1315 choice_strings
[4] = wxT("Other");
1317 pNativeLangChoice
= new wxChoice(this, EDITOR_DIALOG_LANG_CHOICE
, wxPoint( 17, 346), wxSize(277, -1), 5, choice_strings
);
1318 pNativeLangMsg
= new wxStaticText(this, EDITOR_DIALOG_LANG_MSG
, wxT("Native language:"), wxPoint( 17, 330), wxSize( -1, -1), 0, wxT("NativeLangMsg"));
1320 wxString radio_strings
[2];
1321 radio_strings
[0] = wxT("No");
1322 radio_strings
[1] = wxT("Yes");
1323 pDeveloperRadio
= new wxRadioBox(this,EDITOR_DIALOG_DEVELOPER
, wxT("Developer:"), wxPoint(303, 330), wxSize( -1, -1), 2, radio_strings
, 2, wxHORIZONTAL
);
1324 pJoinDateMsg
= new wxStaticText(this, EDITOR_DIALOG_JOIN_MSG
, wxT("Date joined:"), wxPoint( 17, 380), wxSize( -1, -1), 0, wxT("JoinDateMsg"));
1325 pJoinDateTxt
= new wxTextCtrl(this, EDITOR_DIALOG_JOIN_TEXT
, wxT(""), wxPoint( 17, 397), wxSize(150, 25), 0, wxDefaultValidator
, wxT("JoinDateTxt"));
1326 pContribMsg
= new wxStaticText(this, EDITOR_DIALOG_CONTRIB_MSG
,wxT("Contributions:"), wxPoint(175, 380), wxSize( -1, -1), 0, wxT("ContribMsg"));
1327 pContribTxt
= new wxTextCtrl(this, EDITOR_DIALOG_CONTRIB_TEXT
, wxT(""), wxPoint(175, 397), wxSize(120, 25), 0, wxDefaultValidator
, wxT("ContribTxt"));
1328 pLinesMsg
= new wxStaticText(this, EDITOR_DIALOG_LINES_MSG
, wxT("Lines of code:"), wxPoint(303, 380), wxSize( -1, -1), 0, wxT("LinesMsg"));
1329 pLinesTxt
= new wxTextCtrl(this, EDITOR_DIALOG_LINES_TEXT
, wxT(""), wxPoint(303, 397), wxSize(100, 25), 0, wxDefaultValidator
, wxT("LinesTxt"));
1331 pCatalogBtn
= new wxButton(this, EDITOR_DIALOG_CATALOG
, wxT("Catalo&g"), wxPoint(430, 287), wxSize( 70, 35), 0, wxDefaultValidator
, wxT("CatalogBtn"));
1332 pDataTypesBtn
= new wxButton(this, EDITOR_DIALOG_DATATYPES
, wxT("Data&types"), wxPoint(430, 337), wxSize( 70, 35), 0, wxDefaultValidator
, wxT("DataTypesBtn"));
1333 pDbDiagsBtn
= new wxButton(this, EDITOR_DIALOG_DB_DIAGS
, wxT("DB Dia&gs"), wxPoint(430, 387), wxSize( 70, 35), 0, wxDefaultValidator
, wxT("DbDiagsBtn"));
1335 // Now that all the widgets on the panel are created, its safe to allow ::OnCommand() to
1336 // handle all widget processing
1337 widgetPtrsSet
= TRUE
;
1339 // Setup the orderBy and where clauses to return back a single record as the result set,
1340 // as there will only be one record being shown on the dialog at a time, this optimizes
1341 // network traffic by only returning a one row result
1343 wxGetApp().Contact
->SetOrderByClause(wxT("NAME")); // field name to sort by
1345 // The wxString "whereStr" is not a member of the wxDbTable object, it is a member variable
1346 // specifically in the Ccontact class. It is used here for simpler construction of a varying
1347 // length string, and then after the string is built, the wxDbTable member variable "where" is
1348 // assigned the pointer to the constructed string.
1350 // The constructed where clause below has a sub-query within it "SELECT MIN(NAME) FROM %s"
1351 // to achieve a single row (in this case the first name in alphabetical order).
1353 if (wxGetApp().Contact
->GetDb()->Dbms() != dbmsPOSTGRES
&&
1354 wxGetApp().Contact
->GetDb()->Dbms() != dbmsMY_SQL
)
1356 wxGetApp().Contact
->whereStr
.Printf(wxT("NAME = (SELECT MIN(NAME) FROM %s)"),
1357 wxGetApp().Contact
->GetTableName().c_str());
1358 // NOTE: (const wxChar*) returns a pointer which may not be valid later, so this is short term use only
1359 wxGetApp().Contact
->SetWhereClause(wxGetApp().Contact
->whereStr
);
1362 wxGetApp().Contact
->SetWhereClause(wxT(""));
1364 // Perform the Query to get the result set.
1365 // NOTE: If there are no rows returned, that is a valid result, so Query() would return TRUE.
1366 // Only if there is a database error will Query() come back as FALSE
1367 if (!wxGetApp().Contact
->Query())
1370 tStr
= wxT("ODBC error during Query()\n\n");
1371 wxMessageBox(wxDbLogExtendedErrorMsg(tStr
.c_str(),wxGetApp().Contact
->GetDb(),__FILE__
,__LINE__
),
1372 wxT("ODBC Error..."),wxOK
| wxICON_EXCLAMATION
);
1376 // Since Query succeeded, now get the row that was returned
1377 if (!wxGetApp().Contact
->GetNext())
1378 // If the GetNext() failed at this point, then there are no rows to retrieve,
1379 // so clear the values in the members of "Contact" so that PutData() blanks the
1380 // widgets on the dialog
1381 wxGetApp().Contact
->Initialize();
1383 wxGetApp().Contact->GetDb()->RollbackTrans();
1392 } // CeditorDlg::Initialize()
1395 void CeditorDlg::FieldsEditable()
1400 pNameTxt
->Enable((mode
== mCreate
) || (mode
== mEdit
));
1401 pAddress1Txt
->Enable((mode
== mCreate
) || (mode
== mEdit
));
1402 pAddress2Txt
->Enable((mode
== mCreate
) || (mode
== mEdit
));
1403 pCityTxt
->Enable((mode
== mCreate
) || (mode
== mEdit
));
1404 pStateTxt
->Enable((mode
== mCreate
) || (mode
== mEdit
));
1405 pPostalCodeTxt
->Enable((mode
== mCreate
) || (mode
== mEdit
));
1406 pCountryTxt
->Enable((mode
== mCreate
) || (mode
== mEdit
));
1408 pJoinDateTxt
->Enable((mode
== mCreate
) || (mode
== mEdit
));
1409 pContribTxt
->Enable((mode
== mCreate
) || (mode
== mEdit
));
1410 pLinesTxt
->Enable((mode
== mCreate
) || (mode
== mEdit
));
1411 pNativeLangChoice
->Enable((mode
== mCreate
) || (mode
== mEdit
));
1412 pDeveloperRadio
->Enable((mode
== mCreate
) || (mode
== mEdit
));
1414 } // CeditorDlg::FieldsEditable()
1417 void CeditorDlg::SetMode(enum DialogModes m
)
1438 pCreateBtn
->Enable( !edit
);
1439 pEditBtn
->Enable( !edit
&& (wxStrcmp(wxGetApp().Contact
->Name
,wxT(""))!=0) );
1440 pDeleteBtn
->Enable( !edit
&& (wxStrcmp(wxGetApp().Contact
->Name
,wxT(""))!=0) );
1441 pCopyBtn
->Enable( !edit
&& (wxStrcmp(wxGetApp().Contact
->Name
,wxT(""))!=0) );
1442 pSaveBtn
->Enable( edit
);
1443 pCancelBtn
->Enable( edit
);
1444 pPrevBtn
->Enable( !edit
);
1445 pNextBtn
->Enable( !edit
);
1446 pQueryBtn
->Enable( !edit
);
1447 pResetBtn
->Enable( !edit
&& !wxGetApp().Contact
->qryWhereStr
.IsEmpty() );
1448 pNameListBtn
->Enable( !edit
);
1452 } // CeditorDlg::SetMode()
1455 bool CeditorDlg::PutData()
1459 pNameTxt
->SetValue(wxGetApp().Contact
->Name
);
1460 pAddress1Txt
->SetValue(wxGetApp().Contact
->Addr1
);
1461 pAddress2Txt
->SetValue(wxGetApp().Contact
->Addr2
);
1462 pCityTxt
->SetValue(wxGetApp().Contact
->City
);
1463 pStateTxt
->SetValue(wxGetApp().Contact
->State
);
1464 pCountryTxt
->SetValue(wxGetApp().Contact
->Country
);
1465 pPostalCodeTxt
->SetValue(wxGetApp().Contact
->PostalCode
);
1467 tStr
.Printf(wxT("%d/%d/%d"),wxGetApp().Contact
->JoinDate
.month
,wxGetApp().Contact
->JoinDate
.day
,wxGetApp().Contact
->JoinDate
.year
);
1468 pJoinDateTxt
->SetValue(tStr
);
1470 tStr
.Printf(wxT("%d"),wxGetApp().Contact
->Contributions
);
1471 pContribTxt
->SetValue(tStr
);
1473 tStr
.Printf(wxT("%lu"),wxGetApp().Contact
->LinesOfCode
);
1474 pLinesTxt
->SetValue(tStr
);
1476 pNativeLangChoice
->SetSelection(wxGetApp().Contact
->NativeLanguage
);
1478 pDeveloperRadio
->SetSelection(wxGetApp().Contact
->IsDeveloper
);
1481 } // Ceditor::PutData()
1485 * Reads the data out of all the widgets on the dialog. Some data evaluation is done
1486 * to ensure that there is a name entered and that the date field is valid.
1488 * A return value of TRUE means that valid data was retrieved from the dialog, otherwise
1489 * invalid data was found (and a message was displayed telling the user what to fix), and
1490 * the data was not placed into the appropraite fields of Ccontact
1492 bool CeditorDlg::GetData()
1494 // Validate that the data currently entered into the widgets is valid data
1497 tStr
= pNameTxt
->GetValue();
1498 if (!wxStrcmp((const wxChar
*) tStr
,wxT("")))
1500 wxMessageBox(wxT("A name is required for entry into the contact table"),wxT("Notice..."),wxOK
| wxICON_INFORMATION
);
1504 bool invalid
= FALSE
;
1505 int mm
= 1,dd
= 1,yyyy
= 2001;
1508 tStr
= pJoinDateTxt
->GetValue();
1509 if (tStr
.Freq(wxT('/')) != 2)
1512 // Find the month, day, and year tokens
1515 first
= tStr
.First(wxT('/'));
1516 second
= tStr
.Last(wxT('/'));
1518 mm
= atoi(tStr
.SubString(0,first
));
1519 dd
= atoi(tStr
.SubString(first
+1,second
));
1520 yyyy
= atoi(tStr
.SubString(second
+1,tStr
.Length()-1));
1522 invalid
= !(mm
&& dd
&& yyyy
);
1525 // Force Year 2000 compliance
1526 if (!invalid
&& (yyyy
< 1000))
1529 // Check the token ranges for validity
1534 else if ((mm
< 1) || (mm
> 12))
1542 int days
[12] = {31,28,31,30,31,30,
1544 if (dd
> days
[mm
-1])
1547 if ((dd
== 29) && (mm
== 2))
1549 if (((yyyy
% 4) == 0) && (((yyyy
% 100) != 0) || ((yyyy
% 400) == 0)))
1559 wxGetApp().Contact
->JoinDate
.month
= mm
;
1560 wxGetApp().Contact
->JoinDate
.day
= dd
;
1561 wxGetApp().Contact
->JoinDate
.year
= yyyy
;
1565 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
);
1569 tStr
= pNameTxt
->GetValue();
1570 wxStrcpy(wxGetApp().Contact
->Name
,(const wxChar
*) tStr
);
1571 wxStrcpy(wxGetApp().Contact
->Addr1
,pAddress1Txt
->GetValue());
1572 wxStrcpy(wxGetApp().Contact
->Addr2
,pAddress2Txt
->GetValue());
1573 wxStrcpy(wxGetApp().Contact
->City
,pCityTxt
->GetValue());
1574 wxStrcpy(wxGetApp().Contact
->State
,pStateTxt
->GetValue());
1575 wxStrcpy(wxGetApp().Contact
->Country
,pCountryTxt
->GetValue());
1576 wxStrcpy(wxGetApp().Contact
->PostalCode
,pPostalCodeTxt
->GetValue());
1578 wxGetApp().Contact
->Contributions
= atoi(pContribTxt
->GetValue());
1579 wxGetApp().Contact
->LinesOfCode
= atol(pLinesTxt
->GetValue());
1581 wxGetApp().Contact
->NativeLanguage
= (enum Language
) pNativeLangChoice
->GetSelection();
1582 wxGetApp().Contact
->IsDeveloper
= pDeveloperRadio
->GetSelection() > 0;
1585 } // CeditorDlg::GetData()
1589 * Retrieve data from the dialog, verify the validity of the data, and if it is valid,
1590 * try to insert/update the data to the table based on the current 'mode' the dialog
1593 * A return value of TRUE means the insert/update was completed successfully, a return
1594 * value of FALSE means that Save() failed. If returning FALSE, then this function
1595 * has displayed a detailed error message for the user.
1597 bool CeditorDlg::Save()
1599 bool failed
= FALSE
;
1601 // Read the data in the widgets of the dialog to get the user's data
1605 // Perform any other required validations necessary before saving
1608 wxBeginBusyCursor();
1610 if (mode
== mCreate
)
1612 RETCODE result
= wxGetApp().Contact
->Insert();
1614 failed
= (result
!= DB_SUCCESS
);
1617 // Some errors may be expected, like a duplicate key, so handle those instances with
1618 // specific error messages.
1619 if (result
== DB_ERR_INTEGRITY_CONSTRAINT_VIOL
)
1622 tStr
= wxT("A duplicate key value already exists in the table.\nUnable to save record\n\n");
1623 wxMessageBox(wxDbLogExtendedErrorMsg(tStr
.c_str(),wxGetApp().Contact
->GetDb(),__FILE__
,__LINE__
),
1624 wxT("ODBC Error..."),wxOK
| wxICON_EXCLAMATION
);
1628 // Some other unexpected error occurred
1630 tStr
= wxT("Database insert failed\n\n");
1631 wxMessageBox(wxDbLogExtendedErrorMsg(tStr
.c_str(),wxGetApp().Contact
->GetDb(),__FILE__
,__LINE__
),
1632 wxT("ODBC Error..."),wxOK
| wxICON_EXCLAMATION
);
1636 else // mode == mEdit
1638 wxGetApp().Contact
->GetDb()->RollbackTrans();
1639 wxGetApp().Contact
->whereStr
.Printf("NAME = '%s'",saveName
.c_str());
1640 if (!wxGetApp().Contact
->UpdateWhere(wxGetApp().Contact
->whereStr
))
1643 tStr
= wxT("Database update failed\n\n");
1644 wxMessageBox(wxDbLogExtendedErrorMsg(tStr
.c_str(),wxGetApp().Contact
->GetDb(),__FILE__
,__LINE__
),
1645 wxT("ODBC Error..."),wxOK
| wxICON_EXCLAMATION
);
1652 wxGetApp().Contact
->GetDb()->CommitTrans();
1653 SetMode(mView
); // Sets the dialog mode back to viewing after save is successful
1656 wxGetApp().Contact
->GetDb()->RollbackTrans();
1662 } // CeditorDlg::Save()
1666 * Where this program is only showing a single row at a time in the dialog,
1667 * a special where clause must be built to find just the single row which,
1668 * in sequence, would follow the currently displayed row.
1670 bool CeditorDlg::GetNextRec()
1674 if (wxGetApp().Contact
->GetDb()->Dbms() != dbmsPOSTGRES
&&
1675 wxGetApp().Contact
->GetDb()->Dbms() != dbmsMY_SQL
)
1677 w
= wxT("NAME = (SELECT MIN(NAME) FROM ");
1678 w
+= wxGetApp().Contact
->GetTableName();
1679 w
+= wxT(" WHERE NAME > '");
1682 w
= wxT("(NAME > '");
1684 w
+= wxGetApp().Contact
->Name
;
1687 // If a query where string is currently set, append that criteria
1688 if (!wxGetApp().Contact
->qryWhereStr
.IsEmpty())
1691 w
+= wxGetApp().Contact
->qryWhereStr
;
1698 } // CeditorDlg::GetNextRec()
1702 * Where this program is only showing a single row at a time in the dialog,
1703 * a special where clause must be built to find just the single row which,
1704 * in sequence, would precede the currently displayed row.
1706 bool CeditorDlg::GetPrevRec()
1710 if (wxGetApp().Contact
->GetDb()->Dbms() != dbmsPOSTGRES
&&
1711 wxGetApp().Contact
->GetDb()->Dbms() != dbmsMY_SQL
)
1713 w
= wxT("NAME = (SELECT MAX(NAME) FROM ");
1714 w
+= wxGetApp().Contact
->GetTableName();
1715 w
+= wxT(" WHERE NAME < '");
1718 w
= wxT("(NAME < '");
1720 w
+= wxGetApp().Contact
->Name
;
1723 // If a query where string is currently set, append that criteria
1724 if (!wxGetApp().Contact
->qryWhereStr
.IsEmpty())
1727 w
+= wxGetApp().Contact
->qryWhereStr
;
1735 } // CeditorDlg::GetPrevRec()
1739 * This function is here to avoid duplicating this same code in both the
1740 * GetPrevRec() and GetNextRec() functions
1742 bool CeditorDlg::GetRec(const wxString
&whereStr
)
1744 wxGetApp().Contact
->SetWhereClause(whereStr
);
1745 wxGetApp().Contact
->SetOrderByClause(wxT("NAME"));
1747 if (!wxGetApp().Contact
->Query())
1750 tStr
= wxT("ODBC error during Query()\n\n");
1751 wxMessageBox(wxDbLogExtendedErrorMsg(tStr
.c_str(),wxGetApp().Contact
->GetDb(),__FILE__
,__LINE__
),
1752 wxT("ODBC Error..."),wxOK
| wxICON_EXCLAMATION
);
1757 if (wxGetApp().Contact
->GetNext())
1764 } // CeditorDlg::GetRec()
1769 * CparameterDlg constructor
1772 BEGIN_EVENT_TABLE(CparameterDlg
, wxDialog
)
1773 EVT_BUTTON(PARAMETER_DIALOG_SAVE
, CparameterDlg::OnButton
)
1774 EVT_BUTTON(PARAMETER_DIALOG_CANCEL
, CparameterDlg::OnButton
)
1775 EVT_CLOSE(CparameterDlg::OnCloseWindow
)
1778 CparameterDlg::CparameterDlg(wxWindow
*parent
) : wxDialog (parent
, PARAMETER_DIALOG
, wxT("ODBC parameter settings"), wxPoint(-1, -1), wxSize(400, 325))
1780 // Since the ::OnCommand() function is overridden, this prevents the widget
1781 // detection in ::OnCommand() until all widgets have been initialized to prevent
1782 // uninitialized pointers from crashing the program
1783 widgetPtrsSet
= FALSE
;
1785 pParamODBCSourceMsg
= new wxStaticText(this, PARAMETER_DIALOG_SOURCE_MSG
, wxT("ODBC data sources:"), wxPoint( 10, 10), wxSize( -1, -1), 0, wxT("ParamODBCSourceMsg"));
1786 pParamODBCSourceList
= new wxListBox(this, PARAMETER_DIALOG_SOURCE_LISTBOX
, wxPoint( 10, 29), wxSize(285, 150), 0, 0, wxLB_SINGLE
|wxLB_ALWAYS_SB
, wxDefaultValidator
, wxT("ParamODBCSourceList"));
1787 pParamUserNameMsg
= new wxStaticText(this, PARAMETER_DIALOG_NAME_MSG
, wxT("Database user name:"), wxPoint( 10, 193), wxSize( -1, -1), 0, wxT("ParamUserNameMsg"));
1788 pParamUserNameTxt
= new wxTextCtrl(this, PARAMETER_DIALOG_NAME_TEXT
, wxT(""), wxPoint(10, 209), wxSize( 140, 25), 0, wxDefaultValidator
, wxT("ParamUserNameTxt"));
1789 pParamPasswordMsg
= new wxStaticText(this, PARAMETER_DIALOG_PASSWORD_MSG
, wxT("Password:"), wxPoint(156, 193), wxSize( -1, -1), 0, wxT("ParamPasswordMsg"));
1790 pParamPasswordTxt
= new wxTextCtrl(this, PARAMETER_DIALOG_PASSWORD_TEXT
, wxT(""), wxPoint(156, 209), wxSize( 140, 25), 0, wxDefaultValidator
, wxT("ParamPasswordTxt"));
1791 pParamDirPathMsg
= new wxStaticText(this, PARAMETER_DIALOG_DIRPATH_MSG
, wxT("Directory:"), wxPoint( 10, 243), wxSize( -1, -1), 0, wxT("ParamDirPathMsg"));
1792 pParamDirPathTxt
= new wxTextCtrl(this, PARAMETER_DIALOG_DIRPATH_TEXT
, wxT(""), wxPoint( 10, 259), wxSize(140, 25), 0, wxDefaultValidator
, wxT("ParamDirPathTxt"));
1793 pParamSaveBtn
= new wxButton(this, PARAMETER_DIALOG_SAVE
, wxT("&Save"), wxPoint(310, 21), wxSize( 70, 35), 0, wxDefaultValidator
, wxT("ParamSaveBtn"));
1794 pParamCancelBtn
= new wxButton(this, PARAMETER_DIALOG_CANCEL
, wxT("C&ancel"), wxPoint(310, 66), wxSize( 70, 35), 0, wxDefaultValidator
, wxT("ParamCancelBtn"));
1796 // Now that all the widgets on the panel are created, its safe to allow ::OnCommand() to
1797 // handle all widget processing
1798 widgetPtrsSet
= TRUE
;
1801 savedParamSettings
= wxGetApp().params
;
1806 } // CparameterDlg constructor
1809 void CparameterDlg::OnCloseWindow(wxCloseEvent
& event
)
1811 // Put any additional checking necessary to make certain it is alright
1812 // to close the program here that is not done elsewhere
1815 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
);
1823 wxGetApp().params
= savedParamSettings
;
1826 if (GetParent() != NULL
)
1827 GetParent()->SetFocus();
1833 SetReturnCode(0); // added so BoundsChecker would not report use of uninitialized variable
1836 } // CparameterDlg::OnCloseWindow()
1839 void CparameterDlg::OnButton( wxCommandEvent
&event
)
1841 wxWindow
*win
= (wxWindow
*) event
.GetEventObject();
1842 OnCommand( *win
, event
);
1846 void CparameterDlg::OnCommand(wxWindow
& win
, wxCommandEvent
& event
)
1848 wxString widgetName
;
1850 widgetName
= win
.GetName();
1855 if (widgetName
== pParamSaveBtn
->GetName())
1860 tStr
= wxT("Database parameters have been saved.");
1861 if (GetParent() != NULL
) // The parameter dialog was not called during startup due to a missing cfg file
1862 tStr
+= wxT("\nNew parameters will take effect the next time the program is started.");
1863 wxMessageBox(tStr
,wxT("Notice..."),wxOK
| wxICON_INFORMATION
);
1870 if (widgetName
== pParamCancelBtn
->GetName())
1875 } // CparameterDlg::OnCommand()
1878 bool CparameterDlg::PutData()
1880 // Fill the data source list box
1881 FillDataSourceList();
1883 // Fill in the fields from the params object
1884 if (wxGetApp().params
.ODBCSource
&& wxStrlen(wxGetApp().params
.ODBCSource
))
1886 int index
= pParamODBCSourceList
->FindString(wxGetApp().params
.ODBCSource
);
1888 pParamODBCSourceList
->SetSelection(index
);
1890 pParamUserNameTxt
->SetValue(wxGetApp().params
.UserName
);
1891 pParamPasswordTxt
->SetValue(wxGetApp().params
.Password
);
1892 pParamDirPathTxt
->SetValue(wxGetApp().params
.DirPath
);
1894 } // CparameterDlg::PutData()
1897 bool CparameterDlg::GetData()
1900 if (pParamODBCSourceList
->GetStringSelection() != wxT(""))
1902 tStr
= pParamODBCSourceList
->GetStringSelection();
1903 if (tStr
.Length() > (sizeof(wxGetApp().params
.ODBCSource
)-1))
1906 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());
1907 wxMessageBox(errmsg
,wxT("Internal program error..."),wxOK
| wxICON_EXCLAMATION
);
1910 wxStrcpy(wxGetApp().params
.ODBCSource
, tStr
);
1915 tStr
= pParamUserNameTxt
->GetValue();
1916 if (tStr
.Length() > (sizeof(wxGetApp().params
.UserName
)-1))
1919 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());
1920 wxMessageBox(errmsg
,wxT("Internal program error..."),wxOK
| wxICON_EXCLAMATION
);
1923 wxStrcpy(wxGetApp().params
.UserName
, tStr
);
1925 tStr
= pParamPasswordTxt
->GetValue();
1926 if (tStr
.Length() > (sizeof(wxGetApp().params
.Password
)-1))
1929 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());
1930 wxMessageBox(errmsg
,wxT("Internal program error..."),wxOK
| wxICON_EXCLAMATION
);
1933 wxStrcpy(wxGetApp().params
.Password
,tStr
);
1935 tStr
= pParamDirPathTxt
->GetValue();
1936 tStr
.Replace(wxT("\\"),wxT("/"));
1937 if (tStr
.Length() > (sizeof(wxGetApp().params
.DirPath
)-1))
1940 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());
1941 wxMessageBox(errmsg
,wxT("Internal program error..."),wxOK
| wxICON_EXCLAMATION
);
1944 wxStrcpy(wxGetApp().params
.DirPath
,tStr
);
1946 } // CparameterDlg::GetData()
1949 bool CparameterDlg::Save()
1951 // Copy the current params in case user cancels changing
1952 // the params, so that we can reset them.
1955 wxGetApp().params
= savedParamSettings
;
1959 wxGetApp().WriteParamFile(wxGetApp().params
);
1962 } // CparameterDlg::Save()
1965 void CparameterDlg::FillDataSourceList()
1967 wxChar Dsn
[SQL_MAX_DSN_LENGTH
+ 1];
1969 wxStringList strList
;
1971 while (wxDbGetDataSource(wxGetApp().DbConnectInf
->GetHenv(), Dsn
,
1972 SQL_MAX_DSN_LENGTH
+1, DsDesc
, 255))
1976 strList
.Add(wxT(""));
1977 wxChar
**p
= strList
.ListToArray();
1980 for (i
= 0; wxStrlen(p
[i
]); i
++)
1981 pParamODBCSourceList
->Append(p
[i
]);
1984 } // CparameterDlg::FillDataSourceList()
1987 BEGIN_EVENT_TABLE(CqueryDlg
, wxDialog
)
1988 EVT_BUTTON(-1, CqueryDlg::OnButton
)
1989 EVT_CLOSE(CqueryDlg::OnCloseWindow
)
1993 // CqueryDlg() constructor
1994 CqueryDlg::CqueryDlg(wxWindow
*parent
, wxDb
*pDb
, wxChar
*tblName
[],
1995 const wxString
&pWhereArg
) :
1996 wxDialog (parent
, QUERY_DIALOG
, wxT("Query"), wxPoint(-1, -1), wxSize(480, 360))
1998 wxBeginBusyCursor();
2002 masterTableName
= tblName
[0];
2003 widgetPtrsSet
= FALSE
;
2006 // Initialize the WHERE clause from the string passed in
2007 pWhere
= pWhereArg
; // Save a pointer to the output buffer
2008 if (pWhere
.Length() > (unsigned int)DB_MAX_WHERE_CLAUSE_LEN
) // Check the length of the buffer passed in
2011 s
.Printf(wxT("Maximum where clause length exceeded.\nLength must be less than %d"), DB_MAX_WHERE_CLAUSE_LEN
+1);
2012 wxMessageBox(s
,wxT("Error..."),wxOK
| wxICON_EXCLAMATION
);
2017 pQueryCol1Msg
= new wxStaticText(this, QUERY_DIALOG_COL_MSG
, wxT("Column 1:"), wxPoint( 10, 10), wxSize( 69, 16), 0, wxT("QueryCol1Msg"));
2018 pQueryCol1Choice
= new wxChoice(this, QUERY_DIALOG_COL_CHOICE
, wxPoint( 10, 27), wxSize(250, 27), 0, 0, 0, wxDefaultValidator
, wxT("QueryCol1Choice"));
2019 pQueryNotMsg
= new wxStaticText(this, QUERY_DIALOG_NOT_MSG
, wxT("NOT"), wxPoint(268, 10), wxSize( -1, -1), 0, wxT("QueryNotMsg"));
2020 pQueryNotCheck
= new wxCheckBox(this, QUERY_DIALOG_NOT_CHECKBOX
, wxT(""), wxPoint(275, 37), wxSize( 20, 20), 0, wxDefaultValidator
, wxT("QueryNotCheck"));
2022 wxString choice_strings
[9];
2023 choice_strings
[0] = wxT("=");
2024 choice_strings
[1] = wxT("<");
2025 choice_strings
[2] = wxT(">");
2026 choice_strings
[3] = wxT("<=");
2027 choice_strings
[4] = wxT(">=");
2028 choice_strings
[5] = wxT("Begins");
2029 choice_strings
[6] = wxT("Contains");
2030 choice_strings
[7] = wxT("Like");
2031 choice_strings
[8] = wxT("Between");
2033 pQueryOperatorMsg
= new wxStaticText(this, QUERY_DIALOG_OP_MSG
, wxT("Operator:"), wxPoint(305, 10), wxSize( -1, -1), 0, wxT("QueryOperatorMsg"));
2034 pQueryOperatorChoice
= new wxChoice(this, QUERY_DIALOG_OP_CHOICE
, wxPoint(305, 27), wxSize( 80, 27), 9, choice_strings
, 0, wxDefaultValidator
, wxT("QueryOperatorChoice"));
2035 pQueryCol2Msg
= new wxStaticText(this, QUERY_DIALOG_COL2_MSG
, wxT("Column 2:"), wxPoint( 10, 65), wxSize( 69, 16), 0, wxT("QueryCol2Msg"));
2036 pQueryCol2Choice
= new wxChoice(this, QUERY_DIALOG_COL2_CHOICE
, wxPoint( 10, 82), wxSize(250, 27), 0, 0, 0, wxDefaultValidator
, wxT("QueryCol2Choice"));
2037 pQuerySqlWhereMsg
= new wxStaticText(this, QUERY_DIALOG_WHERE_MSG
, wxT("SQL where clause:"), wxPoint( 10, 141), wxSize( -1, -1), 0, wxT("QuerySqlWhereMsg"));
2038 pQuerySqlWhereMtxt
= new wxTextCtrl(this, QUERY_DIALOG_WHERE_TEXT
, wxT(""), wxPoint( 10, 159), wxSize(377, 134), wxTE_MULTILINE
, wxDefaultValidator
, wxT("QuerySqlWhereMtxt"));
2039 pQueryAddBtn
= new wxButton(this, QUERY_DIALOG_ADD
, wxT("&Add"), wxPoint(406, 24), wxSize( 56, 26), 0, wxDefaultValidator
, wxT("QueryAddBtn"));
2040 pQueryAndBtn
= new wxButton(this, QUERY_DIALOG_AND
, wxT("A&nd"), wxPoint(406, 58), wxSize( 56, 26), 0, wxDefaultValidator
, wxT("QueryAndBtn"));
2041 pQueryOrBtn
= new wxButton(this, QUERY_DIALOG_OR
, wxT("&Or"), wxPoint(406, 92), wxSize( 56, 26), 0, wxDefaultValidator
, wxT("QueryOrBtn"));
2042 pQueryLParenBtn
= new wxButton(this, QUERY_DIALOG_LPAREN
, wxT("("), wxPoint(406, 126), wxSize( 26, 26), 0, wxDefaultValidator
, wxT("QueryLParenBtn"));
2043 pQueryRParenBtn
= new wxButton(this, QUERY_DIALOG_RPAREN
, wxT(")"), wxPoint(436, 126), wxSize( 26, 26), 0, wxDefaultValidator
, wxT("QueryRParenBtn"));
2044 pQueryDoneBtn
= new wxButton(this, QUERY_DIALOG_DONE
, wxT("&Done"), wxPoint(406, 185), wxSize( 56, 26), 0, wxDefaultValidator
, wxT("QueryDoneBtn"));
2045 pQueryClearBtn
= new wxButton(this, QUERY_DIALOG_CLEAR
, wxT("C&lear"), wxPoint(406, 218), wxSize( 56, 26), 0, wxDefaultValidator
, wxT("QueryClearBtn"));
2046 pQueryCountBtn
= new wxButton(this, QUERY_DIALOG_COUNT
, wxT("&Count"), wxPoint(406, 252), wxSize( 56, 26), 0, wxDefaultValidator
, wxT("QueryCountBtn"));
2047 pQueryValue1Msg
= new wxStaticText(this, QUERY_DIALOG_VALUE1_MSG
, wxT("Value:"), wxPoint(277, 66), wxSize( -1, -1), 0, wxT("QueryValue1Msg"));
2048 pQueryValue1Txt
= new wxTextCtrl(this, QUERY_DIALOG_VALUE1_TEXT
, wxT(""), wxPoint(277, 83), wxSize(108, 25), 0, wxDefaultValidator
, wxT("QueryValue1Txt"));
2049 pQueryValue2Msg
= new wxStaticText(this, QUERY_DIALOG_VALUE2_MSG
, wxT("AND"), wxPoint(238, 126), wxSize( -1, -1), 0, wxT("QueryValue2Msg"));
2050 pQueryValue2Txt
= new wxTextCtrl(this, QUERY_DIALOG_VALUE2_TEXT
, wxT(""), wxPoint(277, 120), wxSize(108, 25), 0, wxDefaultValidator
, wxT("QueryValue2Txt"));
2051 pQueryHintGrp
= new wxStaticBox(this, QUERY_DIALOG_HINT_GROUP
, wxT(""), wxPoint( 10, 291), wxSize(377, 40), 0, wxT("QueryHintGrp"));
2052 pQueryHintMsg
= new wxStaticText(this, QUERY_DIALOG_HINT_MSG
, wxT(""), wxPoint( 16, 306), wxSize( -1, -1), 0, wxT("QueryHintMsg"));
2054 widgetPtrsSet
= TRUE
;
2055 // Initialize the dialog
2057 pQueryCol2Choice
->Append(wxT("VALUE -->"));
2058 colInf
= pDB
->GetColumns(tblName
);
2064 tStr
= wxT("ODBC error during GetColumns()\n\n");
2065 wxMessageBox(wxDbLogExtendedErrorMsg(tStr
.c_str(),wxGetApp().Contact
->GetDb(),__FILE__
,__LINE__
),
2066 wxT("ODBC Error..."),wxOK
| wxICON_EXCLAMATION
);
2071 for (i
= 0; colInf
[i
].colName
&& wxStrlen(colInf
[i
].colName
); i
++)
2073 // If there is more than one table being queried, qualify
2074 // the column names with the table name prefix.
2075 if (tblName
[1] && wxStrlen(tblName
[1]))
2077 qualName
.Printf(wxT("%s.%s"), colInf
[i
].tableName
, colInf
[i
].colName
);
2078 pQueryCol1Choice
->Append(qualName
);
2079 pQueryCol2Choice
->Append(qualName
);
2081 else // Single table query, append just the column names
2083 pQueryCol1Choice
->Append(colInf
[i
].colName
);
2084 pQueryCol2Choice
->Append(colInf
[i
].colName
);
2088 pQueryCol1Choice
->SetSelection(0);
2089 pQueryCol2Choice
->SetSelection(0);
2090 pQueryOperatorChoice
->SetSelection(0);
2092 pQueryValue2Msg
->Show(FALSE
);
2093 pQueryValue2Txt
->Show(FALSE
);
2095 pQueryHintMsg
->SetLabel(langQRY_EQ
);
2097 pQuerySqlWhereMtxt
->SetValue(pWhere
.c_str());
2101 // Display the dialog window
2104 } // CqueryDlg() constructor
2107 CqueryDlg::~CqueryDlg()
2109 } // CqueryDlg::~CqueryDlg() destructor
2112 void CqueryDlg::OnButton(wxCommandEvent
&event
)
2114 wxWindow
*win
= (wxWindow
*) event
.GetEventObject();
2115 OnCommand( *win
, event
);
2116 } // CqueryDlg::OnButton()
2119 void CqueryDlg::OnCommand(wxWindow
& win
, wxCommandEvent
& event
)
2121 // Widget pointers won't be set when the dialog is constructed.
2122 // Control is passed through this function once for each widget on
2123 // a dialog as the dialog is constructed.
2127 wxString widgetName
= win
.GetName();
2129 // Operator choice box
2130 if (widgetName
== pQueryOperatorChoice
->GetName())
2132 // Set the help text
2133 switch((qryOp
) pQueryOperatorChoice
->GetSelection())
2136 pQueryHintMsg
->SetLabel(langQRY_EQ
);
2139 pQueryHintMsg
->SetLabel(langQRY_LT
);
2142 pQueryHintMsg
->SetLabel(langQRY_GT
);
2145 pQueryHintMsg
->SetLabel(langQRY_LE
);
2148 pQueryHintMsg
->SetLabel(langQRY_GE
);
2151 pQueryHintMsg
->SetLabel(langQRY_BEGINS
);
2154 pQueryHintMsg
->SetLabel(langQRY_CONTAINS
);
2157 pQueryHintMsg
->SetLabel(langQRY_LIKE
);
2160 pQueryHintMsg
->SetLabel(langQRY_BETWEEN
);
2164 // Hide the value2 widget
2165 pQueryValue2Msg
->Show(FALSE
); // BETWEEN will show this widget
2166 pQueryValue2Txt
->Show(FALSE
); // BETWEEN will show this widget
2168 // Disable the NOT operator for <, <=, >, >=
2169 switch((qryOp
) pQueryOperatorChoice
->GetSelection())
2175 pQueryNotCheck
->SetValue(0);
2176 pQueryNotCheck
->Enable(FALSE
);
2179 pQueryNotCheck
->Enable(TRUE
);
2183 // Manipulate the dialog to handle the selected operator
2184 switch((qryOp
) pQueryOperatorChoice
->GetSelection())
2191 pQueryCol2Choice
->Enable(TRUE
);
2192 if (pQueryCol2Choice
->GetSelection()) // Column name is highlighted
2194 pQueryValue1Msg
->Show(FALSE
);
2195 pQueryValue1Txt
->Show(FALSE
);
2197 else // "Value" is highlighted
2199 pQueryValue1Msg
->Show(TRUE
);
2200 pQueryValue1Txt
->Show(TRUE
);
2201 pQueryValue1Txt
->SetFocus();
2207 pQueryCol2Choice
->SetSelection(0);
2208 pQueryCol2Choice
->Enable(FALSE
);
2209 pQueryValue1Msg
->Show(TRUE
);
2210 pQueryValue1Txt
->Show(TRUE
);
2211 pQueryValue1Txt
->SetFocus();
2214 pQueryCol2Choice
->SetSelection(0);
2215 pQueryCol2Choice
->Enable(FALSE
);
2216 pQueryValue2Msg
->Show(TRUE
);
2217 pQueryValue2Txt
->Show(TRUE
);
2218 pQueryValue1Msg
->Show(TRUE
);
2219 pQueryValue1Txt
->Show(TRUE
);
2220 pQueryValue1Txt
->SetFocus();
2226 } // Operator choice box
2229 if (widgetName
== pQueryCol2Choice
->GetName())
2231 if (pQueryCol2Choice
->GetSelection()) // Column name is highlighted
2233 pQueryValue1Msg
->Show(FALSE
);
2234 pQueryValue1Txt
->Show(FALSE
);
2236 else // "Value" is highlighted
2238 pQueryValue1Msg
->Show(TRUE
);
2239 pQueryValue1Txt
->Show(TRUE
);
2240 pQueryValue1Txt
->SetFocus();
2243 } // Column 2 choice
2246 if (widgetName
== pQueryAddBtn
->GetName())
2253 if (widgetName
== pQueryAndBtn
->GetName())
2255 AppendToWhere(wxT(" AND\n"));
2260 if (widgetName
== pQueryOrBtn
->GetName())
2262 AppendToWhere(wxT(" OR\n"));
2266 // Left Paren button
2267 if (widgetName
== pQueryLParenBtn
->GetName())
2269 AppendToWhere(wxT("("));
2271 } // Left Paren button
2273 // Right paren button
2274 if (widgetName
== pQueryRParenBtn
->GetName())
2276 AppendToWhere(wxT(")"));
2278 } // Right Paren button
2281 if (widgetName
== pQueryDoneBtn
->GetName())
2283 // Be sure the where clause will not overflow the output buffer
2284 if (wxStrlen(pQuerySqlWhereMtxt
->GetValue()) > (unsigned int)DB_MAX_WHERE_CLAUSE_LEN
)
2287 s
.Printf(wxT("Maximum where clause length exceeded.\nLength must be less than %d"), DB_MAX_WHERE_CLAUSE_LEN
+1);
2288 wxMessageBox(s
,wxT("Error..."),wxOK
| wxICON_EXCLAMATION
);
2291 // Validate the where clause for things such as matching parens
2292 if (!ValidateWhereClause())
2294 // Copy the where clause to the output buffer and exit
2295 pWhere
= pQuerySqlWhereMtxt
->GetValue();
2301 if (widgetName
== pQueryClearBtn
->GetName())
2303 bool Ok
= (wxMessageBox(wxT("Are you sure you wish to clear the Query?"),wxT("Confirm"),wxYES_NO
|wxICON_QUESTION
) == wxYES
);
2306 pQuerySqlWhereMtxt
->SetValue(wxT(""));
2311 if (widgetName
== pQueryCountBtn
->GetName())
2313 wxBeginBusyCursor();
2319 } // CqueryDlg::OnCommand
2322 void CqueryDlg::OnCloseWindow(wxCloseEvent
& event
)
2329 GetParent()->SetFocus();
2334 SetReturnCode(1); // added so BoundsChecker would not report use of uninitialized variable
2337 } // CqueryDlg::OnCloseWindow()
2340 void CqueryDlg::AppendToWhere(wxChar
*s
)
2342 wxString whereStr
= pQuerySqlWhereMtxt
->GetValue();
2344 pQuerySqlWhereMtxt
->SetValue(whereStr
);
2345 } // CqueryDlg::AppendToWhere()
2348 void CqueryDlg::ProcessAddBtn()
2350 qryOp oper
= (qryOp
) pQueryOperatorChoice
->GetSelection();
2352 // Verify that eveything is filled in correctly
2353 if (pQueryCol2Choice
->GetSelection() == 0) // "Value" is selected
2355 // Verify that value 1 is filled in
2356 if (wxStrlen(pQueryValue1Txt
->GetValue()) == 0)
2359 pQueryValue1Txt
->SetFocus();
2362 // For the BETWEEN operator, value 2 must be filled in as well
2363 if (oper
== qryOpBETWEEN
&&
2364 wxStrlen(pQueryValue2Txt
->GetValue()) == 0)
2367 pQueryValue2Txt
->SetFocus();
2372 // Build the expression and append it to the where clause window
2373 wxString s
= pQueryCol1Choice
->GetStringSelection();
2375 if (pQueryNotCheck
->GetValue() && (oper
!= qryOpEQ
))
2381 if (pQueryNotCheck
->GetValue()) // NOT box is checked
2404 s
+= wxT(" BETWEEN");
2410 int col1Idx
= pQueryCol1Choice
->GetSelection();
2413 if (colInf
[col1Idx
].sqlDataType
== SQL_VARCHAR
||
2414 oper
== qryOpBEGINS
||
2415 oper
== qryOpCONTAINS
||
2419 if (pQueryCol2Choice
->GetSelection()) // Column name
2420 s
+= pQueryCol2Choice
->GetStringSelection();
2421 else // Column 2 is a "value"
2425 if (oper
== qryOpCONTAINS
)
2427 s
+= pQueryValue1Txt
->GetValue();
2428 if (oper
== qryOpCONTAINS
|| oper
== qryOpBEGINS
)
2434 if (oper
== qryOpBETWEEN
)
2439 s
+= pQueryValue2Txt
->GetValue();
2444 AppendToWhere((wxChar
*) (const wxChar
*) s
);
2446 } // CqueryDlg::ProcessAddBtn()
2449 void CqueryDlg::ProcessCountBtn()
2451 if (!ValidateWhereClause())
2454 if (!dbTable
) // wxDbTable object needs to be created and opened
2456 dbTable
= new wxDbTable(pDB
, masterTableName
, 0, wxT(""),
2458 wxGetApp().DbConnectInf
->GetDefaultDir());
2461 wxMessageBox(wxT("Memory allocation failed creating a wxDbTable object."),wxT("Error..."),wxOK
| wxICON_EXCLAMATION
);
2464 if (!dbTable
->Open())
2467 tStr
= wxT("ODBC error during Open()\n\n");
2468 wxMessageBox(wxDbLogExtendedErrorMsg(tStr
.c_str(),wxGetApp().Contact
->GetDb(),__FILE__
,__LINE__
),
2469 wxT("ODBC Error..."),wxOK
| wxICON_EXCLAMATION
);
2474 // Count() with WHERE clause
2477 whereStr
= pQuerySqlWhereMtxt
->GetValue();
2478 dbTable
->SetWhereClause(whereStr
.c_str());
2480 ULONG whereCnt
= dbTable
->Count();
2482 // Count() of all records in the table
2483 dbTable
->SetWhereClause(wxT(""));
2484 ULONG totalCnt
= dbTable
->Count();
2486 if (whereCnt
> 0 || totalCnt
== 0)
2489 tStr
.Printf(wxT("%lu of %lu records match the query criteria."),whereCnt
,totalCnt
);
2490 wxMessageBox(tStr
,wxT("Notice..."),wxOK
| wxICON_INFORMATION
);
2495 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
);
2496 wxMessageBox(tStr
,wxT("Notice..."),wxOK
| wxICON_INFORMATION
);
2499 // After a wxMessageBox, the focus does not necessarily return to the
2500 // window which was the focus when the message box popped up, so return
2501 // focus to the Query dialog for certain
2504 } // CqueryDlg::ProcessCountBtn()
2507 bool CqueryDlg::ValidateWhereClause()
2509 wxString where
= pQuerySqlWhereMtxt
->GetValue();
2511 if (where
.Freq(wxT('(')) != where
.Freq(wxT(')')))
2513 wxMessageBox(wxT("There are mismatched parenthesis in the constructed where clause"),wxT("Error..."),wxOK
| wxICON_EXCLAMATION
);
2516 // After a wxMessageBox, the focus does not necessarily return to the
2517 // window which was the focus when the message box popped up, so return
2518 // focus to the Query dialog for certain
2523 } // CqueryDlg::ValidateWhereClause()
2527 void DisplayDbDiagnostics(wxDb
*pDb
)
2532 s
= langDBINF_DB_NAME
;
2533 s
+= pDb
->dbInf
.dbmsName
;
2536 s
+= langDBINF_DB_VER
;
2537 s
+= pDb
->dbInf
.dbmsVer
;
2540 s
+= langDBINF_DRIVER_NAME
;
2541 s
+= pDb
->dbInf
.driverName
;
2544 s
+= langDBINF_DRIVER_ODBC_VER
;
2545 s
+= pDb
->dbInf
.odbcVer
;
2548 s
+= langDBINF_DRIVER_MGR_ODBC_VER
;
2549 s
+= pDb
->dbInf
.drvMgrOdbcVer
;
2552 s
+= langDBINF_DRIVER_VER
;
2553 s
+= pDb
->dbInf
.driverVer
;
2556 s
+= langDBINF_SERVER_NAME
;
2557 s
+= pDb
->dbInf
.serverName
;
2560 s
+= langDBINF_FILENAME
;
2561 s
+= pDb
->dbInf
.databaseName
;
2564 s
+= langDBINF_OUTER_JOINS
;
2565 s
+= pDb
->dbInf
.outerJoins
;
2568 s
+= langDBINF_STORED_PROC
;
2569 s
+= pDb
->dbInf
.procedureSupport
;
2572 if (pDb
->dbInf
.maxConnections
)
2573 t
.sprintf("%s%d\n", langDBINF_MAX_HDBC
, pDb
->dbInf
.maxConnections
);
2575 t
.sprintf("%s%s\n", langDBINF_MAX_HDBC
, langDBINF_UNLIMITED
);
2578 if (pDb
->dbInf
.maxStmts
)
2579 t
.sprintf("%s%d\n", langDBINF_MAX_HSTMT
, pDb
->dbInf
.maxStmts
);
2581 t
.sprintf("%s%s\n", langDBINF_MAX_HSTMT
, langDBINF_UNLIMITED
);
2584 s
+= langDBINF_API_LVL
;
2585 switch(pDb
->dbInf
.apiConfLvl
)
2587 case SQL_OAC_NONE
: s
+= langDBINF_NONE
; break;
2588 case SQL_OAC_LEVEL1
: s
+= langDBINF_LEVEL1
; break;
2589 case SQL_OAC_LEVEL2
: s
+= langDBINF_LEVEL2
; break;
2593 s
+= langDBINF_CLI_LVL
;
2594 switch(pDb
->dbInf
.cliConfLvl
)
2596 case SQL_OSCC_NOT_COMPLIANT
: s
+= langDBINF_NOT_COMPLIANT
; break;
2597 case SQL_OSCC_COMPLIANT
: s
+= langDBINF_COMPLIANT
; break;
2601 s
+= langDBINF_SQL_LVL
;
2602 switch(pDb
->dbInf
.sqlConfLvl
)
2604 case SQL_OSC_MINIMUM
: s
+= langDBINF_MIN_GRAMMAR
; break;
2605 case SQL_OSC_CORE
: s
+= langDBINF_CORE_GRAMMAR
; break;
2606 case SQL_OSC_EXTENDED
: s
+= langDBINF_EXT_GRAMMAR
; break;
2610 s
+= langDBINF_COMMIT_BEHAVIOR
;
2611 switch(pDb
->dbInf
.cursorCommitBehavior
)
2613 case SQL_CB_DELETE
: s
+= langDBINF_DELETE_CURSORS
; break;
2614 case SQL_CB_CLOSE
: s
+= langDBINF_CLOSE_CURSORS
; break;
2615 case SQL_CB_PRESERVE
: s
+= langDBINF_PRESERVE_CURSORS
; break;
2619 s
+= langDBINF_ROLLBACK_BEHAVIOR
;
2620 switch(pDb
->dbInf
.cursorRollbackBehavior
)
2622 case SQL_CB_DELETE
: s
+= langDBINF_DELETE_CURSORS
; break;
2623 case SQL_CB_CLOSE
: s
+= langDBINF_CLOSE_CURSORS
; break;
2624 case SQL_CB_PRESERVE
: s
+= langDBINF_PRESERVE_CURSORS
; break;
2628 s
+= langDBINF_SUPP_NOT_NULL
;
2629 switch(pDb
->dbInf
.supportNotNullClause
)
2631 case SQL_NNC_NULL
: s
+= langNO
; break;
2632 case SQL_NNC_NON_NULL
: s
+= langYES
; break;
2636 s
+= langDBINF_SUPP_IEF
;
2637 s
+= pDb
->dbInf
.supportIEF
;
2640 // DEFAULT setting for "Transaction Isolation Level"
2641 s
+= langDBINF_TXN_ISOLATION
;
2642 switch(pDb
->dbInf
.txnIsolation
)
2644 case SQL_TXN_READ_UNCOMMITTED
: s
+= langDBINF_READ_UNCOMMITTED
; break;
2645 case SQL_TXN_READ_COMMITTED
: s
+= langDBINF_READ_COMMITTED
; break;
2646 case SQL_TXN_REPEATABLE_READ
: s
+= langDBINF_REPEATABLE_READ
; break;
2647 case SQL_TXN_SERIALIZABLE
: s
+= langDBINF_SERIALIZABLE
; break;
2649 case SQL_TXN_VERSIONING
: s
+= langDBINF_VERSIONING
; break;
2654 // CURRENT setting for "Transaction Isolation Level"
2656 s
+= langDBINF_TXN_ISOLATION_CURR
;
2657 if (SQLGetConnectOption(pDb
->GetHDBC(),SQL_TXN_ISOLATION
,&txnIsoLvl
) == SQL_SUCCESS
)
2661 case SQL_TXN_READ_UNCOMMITTED
: s
+= langDBINF_READ_UNCOMMITTED
; break;
2662 case SQL_TXN_READ_COMMITTED
: s
+= langDBINF_READ_COMMITTED
; break;
2663 case SQL_TXN_REPEATABLE_READ
: s
+= langDBINF_REPEATABLE_READ
; break;
2664 case SQL_TXN_SERIALIZABLE
: s
+= langDBINF_SERIALIZABLE
; break;
2666 case SQL_TXN_VERSIONING
: s
+= langDBINF_VERSIONING
; break;
2673 #pragma message disable incboodep
2676 s
+= langDBINF_TXN_ISOLATION_OPTS
;
2677 if (pDb
->dbInf
.txnIsolationOptions
& SQL_TXN_READ_UNCOMMITTED
)
2678 {s
+= langDBINF_READ_UNCOMMITTED
; comma
++;}
2679 if (pDb
->dbInf
.txnIsolationOptions
& SQL_TXN_READ_COMMITTED
)
2680 {if (comma
++) s
+= ", "; s
+= langDBINF_READ_COMMITTED
;}
2681 if (pDb
->dbInf
.txnIsolationOptions
& SQL_TXN_REPEATABLE_READ
)
2682 {if (comma
++) s
+= ", "; s
+= langDBINF_REPEATABLE_READ
;}
2683 if (pDb
->dbInf
.txnIsolationOptions
& SQL_TXN_SERIALIZABLE
)
2684 {if (comma
++) s
+= ", "; s
+= langDBINF_SERIALIZABLE
;}
2686 if (pDb
->dbInf
.txnIsolationOptions
& SQL_TXN_VERSIONING
)
2687 {if (comma
++) s
+= ", "; s
+= langDBINF_VERSIONING
;}
2692 s
+= langDBINF_FETCH_DIRS
;
2693 if (pDb
->dbInf
.fetchDirections
& SQL_FD_FETCH_NEXT
)
2694 {s
+= langDBINF_NEXT
; comma
++;}
2695 if (pDb
->dbInf
.fetchDirections
& SQL_FD_FETCH_PRIOR
)
2696 {if (comma
++) s
+= ", "; s
+= langDBINF_PREV
;}
2697 if (pDb
->dbInf
.fetchDirections
& SQL_FD_FETCH_FIRST
)
2698 {if (comma
++) s
+= ", "; s
+= langDBINF_FIRST
;}
2699 if (pDb
->dbInf
.fetchDirections
& SQL_FD_FETCH_LAST
)
2700 {if (comma
++) s
+= ", "; s
+= langDBINF_LAST
;}
2701 if (pDb
->dbInf
.fetchDirections
& SQL_FD_FETCH_ABSOLUTE
)
2702 {if (comma
++) s
+= ", "; s
+= langDBINF_ABSOLUTE
;}
2703 if (pDb
->dbInf
.fetchDirections
& SQL_FD_FETCH_RELATIVE
)
2704 {if (comma
++) s
+= ", "; s
+= langDBINF_RELATIVE
;}
2706 if (pDb
->dbInf
.fetchDirections
& SQL_FD_FETCH_RESUME
)
2707 {if (comma
++) s
+= ", "; s
+= langDBINF_RESUME
;}
2709 if (pDb
->dbInf
.fetchDirections
& SQL_FD_FETCH_BOOKMARK
)
2710 {if (comma
++) s
+= ", "; s
+= langDBINF_BOOKMARK
;}
2714 s
+= langDBINF_LOCK_TYPES
;
2715 if (pDb
->dbInf
.lockTypes
& SQL_LCK_NO_CHANGE
)
2716 {s
+= langDBINF_NO_CHANGE
; comma
++;}
2717 if (pDb
->dbInf
.lockTypes
& SQL_LCK_EXCLUSIVE
)
2718 {if (comma
++) s
+= ", "; s
+= langDBINF_EXCLUSIVE
;}
2719 if (pDb
->dbInf
.lockTypes
& SQL_LCK_UNLOCK
)
2720 {if (comma
++) s
+= ", "; s
+= langDBINF_UNLOCK
;}
2724 s
+= langDBINF_POS_OPERS
;
2725 if (pDb
->dbInf
.posOperations
& SQL_POS_POSITION
)
2726 {s
+= langDBINF_POSITION
; comma
++;}
2727 if (pDb
->dbInf
.posOperations
& SQL_POS_REFRESH
)
2728 {if (comma
++) s
+= ", "; s
+= langDBINF_REFRESH
;}
2729 if (pDb
->dbInf
.posOperations
& SQL_POS_UPDATE
)
2730 {if (comma
++) s
+= ", "; s
+= langDBINF_UPD
;}
2731 if (pDb
->dbInf
.posOperations
& SQL_POS_DELETE
)
2732 {if (comma
++) s
+= ", "; s
+= langDBINF_DEL
;}
2733 if (pDb
->dbInf
.posOperations
& SQL_POS_ADD
)
2734 {if (comma
++) s
+= ", "; s
+= langDBINF_ADD
;}
2738 s
+= langDBINF_POS_STMTS
;
2739 if (pDb
->dbInf
.posStmts
& SQL_PS_POSITIONED_DELETE
)
2740 {s
+= langDBINF_POS_DEL
; comma
++;}
2741 if (pDb
->dbInf
.posStmts
& SQL_PS_POSITIONED_UPDATE
)
2742 {if (comma
++) s
+= ", "; s
+= langDBINF_POS_UPD
;}
2743 if (pDb
->dbInf
.posStmts
& SQL_PS_SELECT_FOR_UPDATE
)
2744 {if (comma
++) s
+= ", "; s
+= langDBINF_SELECT_FOR_UPD
;}
2748 s
+= langDBINF_SCROLL_CONCURR
;
2749 if (pDb
->dbInf
.scrollConcurrency
& SQL_SCCO_READ_ONLY
)
2750 {s
+= langDBINF_READ_ONLY
; comma
++;}
2751 if (pDb
->dbInf
.scrollConcurrency
& SQL_SCCO_LOCK
)
2752 {if (comma
++) s
+= ", "; s
+= langDBINF_LOCK
;}
2753 if (pDb
->dbInf
.scrollConcurrency
& SQL_SCCO_OPT_ROWVER
)
2754 {if (comma
++) s
+= ", "; s
+= langDBINF_OPT_ROWVER
;}
2755 if (pDb
->dbInf
.scrollConcurrency
& SQL_SCCO_OPT_VALUES
)
2756 {if (comma
++) s
+= ", "; s
+= langDBINF_OPT_VALUES
;}
2760 s
+= langDBINF_SCROLL_OPTS
;
2761 if (pDb
->dbInf
.scrollOptions
& SQL_SO_FORWARD_ONLY
)
2762 {s
+= langDBINF_FWD_ONLY
; comma
++;}
2763 if (pDb
->dbInf
.scrollOptions
& SQL_SO_STATIC
)
2764 {if (comma
++) s
+= ", "; s
+= langDBINF_STATIC
;}
2765 if (pDb
->dbInf
.scrollOptions
& SQL_SO_KEYSET_DRIVEN
)
2766 {if (comma
++) s
+= ", "; s
+= langDBINF_KEYSET_DRIVEN
;}
2767 if (pDb
->dbInf
.scrollOptions
& SQL_SO_DYNAMIC
)
2768 {if (comma
++) s
+= ", "; s
+= langDBINF_DYNAMIC
;}
2769 if (pDb
->dbInf
.scrollOptions
& SQL_SO_MIXED
)
2770 {if (comma
++) s
+= ", "; s
+= langDBINF_MIXED
;}
2774 s
+= langDBINF_STATIC_SENS
;
2775 if (pDb
->dbInf
.staticSensitivity
& SQL_SS_ADDITIONS
)
2776 {s
+= langDBINF_ADDITIONS
; comma
++;}
2777 if (pDb
->dbInf
.staticSensitivity
& SQL_SS_DELETIONS
)
2778 {if (comma
++) s
+= ", "; s
+= langDBINF_DELETIONS
;}
2779 if (pDb
->dbInf
.staticSensitivity
& SQL_SS_UPDATES
)
2780 {if (comma
++) s
+= ", "; s
+= langDBINF_UPDATES
;}
2783 #pragma message enable incboodep
2787 s
+= langDBINF_TXN_CAPABLE
;
2788 switch(pDb
->dbInf
.txnCapable
)
2790 case SQL_TC_NONE
: s
+= langNO
; break;
2791 case SQL_TC_DML
: s
+= langDBINF_DML_ONLY
; break;
2792 case SQL_TC_DDL_COMMIT
: s
+= langDBINF_DDL_COMMIT
; break;
2793 case SQL_TC_DDL_IGNORE
: s
+= langDBINF_DDL_IGNORE
; break;
2794 case SQL_TC_ALL
: s
+= langDBINF_DDL_AND_DML
; break;
2798 t
.sprintf("%s%d\n", langDBINF_LOGIN_TIMEOUT
, pDb
->dbInf
.loginTimeout
);
2801 // Oracle specific information
2802 if (pDb
->Dbms() == dbmsORACLE
)
2805 s
+= langDBINF_ORACLE_BANNER
;
2808 // Oracle cache hit ratio
2811 pDb
->ExecSql("SELECT VALUE FROM V$SYSSTAT WHERE NAME = 'db block gets'");
2813 if (pDb
->GetData(1, SQL_C_ULONG
, &dbBlockGets
, 0, &cb
))
2815 t
.sprintf("%s: %lu\n", langDBINF_DB_BLOCK_GETS
, dbBlockGets
);
2819 ULONG consistentGets
;
2820 pDb
->ExecSql("SELECT VALUE FROM V$SYSSTAT WHERE NAME = 'consistent gets'");
2822 if (pDb
->GetData(1, SQL_C_ULONG
, &consistentGets
, 0, &cb
))
2824 t
.sprintf("%s: %lu\n", langDBINF_CONSISTENT_GETS
, consistentGets
);
2829 pDb
->ExecSql("SELECT VALUE FROM V$SYSSTAT WHERE NAME = 'physical reads'");
2831 if (pDb
->GetData(1, SQL_C_ULONG
, &physReads
, 0, &cb
))
2833 t
.sprintf("%s: %lu\n", langDBINF_PHYSICAL_READS
, physReads
);
2837 ULONG hitRatio
= (ULONG
)((1.00 - ((float)physReads
/ (float)(dbBlockGets
+ consistentGets
))) * 100.00);
2838 t
.sprintf("*** %s: %lu%%\n", langDBINF_CACHE_HIT_RATIO
, hitRatio
);
2841 // Tablespace information
2843 s
+= langDBINF_TABLESPACE_IO
;
2846 char tablespaceName
[257];
2847 pDb
->ExecSql("SELECT NAME,PHYRDS,PHYWRTS FROM V$DATAFILE, V$FILESTAT WHERE V$DATAFILE.FILE# = V$FILESTAT.FILE#");
2848 while (pDb
->GetNext())
2850 pDb
->GetData(1, SQL_C_CHAR
, tablespaceName
, 257, &cb
);
2851 pDb
->GetData(2, SQL_C_ULONG
, &physReads
, 0, &cb
);
2852 pDb
->GetData(3, SQL_C_ULONG
, &physWrites
, 0, &cb
);
2853 t
.sprintf("%s\n\t%s: %lu\t%s: %lu\n", tablespaceName
,
2854 langDBINF_PHYSICAL_READS
, physReads
, langDBINF_PHYSICAL_WRITES
, physWrites
);
2863 } // DisplayDbDiagnostics()
2867 BEGIN_EVENT_TABLE(DbGridFrame
, wxFrame
)
2868 // EVT_CLOSE(DbGridFrame::OnCloseWindow)
2872 DbGridFrame::DbGridFrame(wxWindow
*parent
)
2873 : wxFrame (parent
, -1, wxT("Database Table"),
2874 wxDefaultPosition
, wxSize(400, 325))
2876 initialized
= FALSE
;
2880 void DbGridFrame::OnCloseWindow(wxCloseEvent
& event
)
2886 bool DbGridFrame::Initialize()
2888 wxGrid
*grid
= new wxGrid(this, -1, wxDefaultPosition
);
2890 grid
->RegisterDataType(wxGRID_VALUE_DATETIME
,
2891 new wxGridCellDateTimeRenderer(_T("%d %b %Y")),
2892 new wxGridCellTextEditor
);
2894 grid
->RegisterDataType(wxGRID_VALUE_CHOICEINT
,
2895 new wxGridCellEnumRenderer
,
2896 new wxGridCellEnumEditor
);
2898 wxString
NativeLangChoice( wxString::Format("%s:%s,%s,%s,%s,%s",wxGRID_VALUE_CHOICEINT
,
2906 // Columns must match the sequence specified in SetColDef() calls
2907 wxDbGridColInfo
* cols
=
2908 new wxDbGridColInfo( 0,wxGRID_VALUE_STRING
,wxT("Name"),
2909 new wxDbGridColInfo( 1,wxGRID_VALUE_STRING
,wxT("Address 1"),
2910 new wxDbGridColInfo( 2,wxGRID_VALUE_STRING
,wxT("Address 2"),
2911 new wxDbGridColInfo( 3,wxGRID_VALUE_STRING
,wxT("City"),
2912 new wxDbGridColInfo( 4,wxGRID_VALUE_STRING
,wxT("State"),
2913 new wxDbGridColInfo( 5,wxGRID_VALUE_STRING
,wxT("PostCode"),
2914 new wxDbGridColInfo( 6,wxGRID_VALUE_STRING
,wxT("Country"),
2915 new wxDbGridColInfo( 7,wxGRID_VALUE_DBAUTO
,wxT("Join Date"),
2916 new wxDbGridColInfo( 8,wxGRID_VALUE_BOOL
, wxT("Developer"),
2917 new wxDbGridColInfo( 9,wxGRID_VALUE_NUMBER
,wxT("Contributions"),
2918 new wxDbGridColInfo(10,wxGRID_VALUE_NUMBER
,wxT("Lines Of Code"),
2920 new wxDbGridColInfo(11,NativeLangChoice
, wxT("Native Language"),NULL
))))))))))));
2922 new wxDbGridColInfo(11,wxGRID_VALUE_NUMBER
,wxT("Native Language"),NULL
))))))))))));
2925 Ccontact
*Contact
= new Ccontact();
2926 //wxGetApp().Contact
2930 wxMessageBox(wxT("Unable to instantiate an instance of Ccontact"), wxT("Error..."), wxOK
| wxICON_EXCLAMATION
);
2934 if (!Contact
->Open())
2936 if (Contact
->GetDb()->TableExists(CONTACT_TABLE_NAME
, Contact
->GetDb()->GetUsername(),
2937 wxGetApp().DbConnectInf
->GetDefaultDir()))
2940 tStr
.Printf(wxT("Unable to open the table '%s'.\n\n"),CONTACT_TABLE_NAME
);
2941 wxMessageBox(wxDbLogExtendedErrorMsg(tStr
.c_str(),wxGetApp().Contact
->GetDb(),__FILE__
,__LINE__
),
2942 wxT("ODBC Error..."),wxOK
| wxICON_EXCLAMATION
);
2948 // Execute the following query using the cursor designated
2949 // for full table query
2950 Contact
->SetRowMode(wxDbTable::WX_ROW_MODE_QUERY
);
2952 if (!Contact
->Query())
2955 tStr
= wxT("ODBC error during Query()\n\n");
2956 wxMessageBox(wxDbLogExtendedErrorMsg(tStr
.c_str(),wxGetApp().Contact
->GetDb(),__FILE__
,__LINE__
),
2957 wxT("ODBC Error..."),wxOK
| wxICON_EXCLAMATION
);
2961 // No data has been read in from the database yet, so
2962 // we need to initialize the data members to valid values
2963 // so Fit() can correctly size the grid
2964 Contact
->Initialize();
2966 wxDbGridTableBase
* db
= new wxDbGridTableBase(Contact
, cols
, wxUSE_QUERY
, TRUE
);
2970 grid
->SetTable(db
,TRUE
);
2971 grid
->SetMargins(0, 0);
2974 wxSize size
= grid
->GetSize();
2977 SetClientSize(size
);
2980 } // DbGridFrame::Initialize()
2982 #endif // #if wxUSE_NEW_GRID
2985 TEST CODE FOR TESTING THE wxDbCreateDataSource() FUNCTION
2988 result = wxDbCreateDataSource(wxT("Microsoft Access Driver (*.mdb)"),wxT("GLT-TEST2"),wxT("GLT-Descrip"),FALSE,wxT(""),this);
2991 // check for errors caused by ConfigDSN based functions
2994 wxChar errMsg[500+1];
2995 errMsg[0] = wxT('\0');
2997 SQLInstallerError(1,&retcode,errMsg,500,&cb);
2999 wxMessageBox(wxT("FAILED creating data source"),wxT("FAILED"));
3002 wxMessageBox(wxT("SUCCEEDED creating data source"),wxT("SUCCESS"));