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 wxTable.
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 wxTable 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 char ListDB_Selection
[]; /* Used to return the first column value for the selected line from the listDB routines */
55 extern char ListDB_Selection2
[]; /* Used to return the second column value for the selected line from the listDB routines */
57 DatabaseDemoFrame
*DemoFrame
; /* Pointer to the main frame */
59 /* Pointer to the main database connection used in the program. This
60 * pointer would normally be used for doing things as database lookups
61 * for user login names and passwords, getting workstation settings, etc.
64 * For each database object created which uses this wxDB pointer
65 * connection to the database, when a CommitTrans() or RollBackTrans()
66 * will commit or rollback EVERY object which uses this wxDB pointer.
68 * To allow each table object (those derived from wxTable) to be
69 * individually committed or rolled back, you MUST use a different
70 * instance of wxDB in the constructor of the table. Doing so creates
71 * more overhead, and will use more database connections (some DBs have
72 * connection limits...), so use connections sparringly.
74 * It is recommended that one "main" database connection be created for
75 * the entire program to use for READ-ONLY database accesses, but for each
76 * table object which will do a CommitTrans() or RollbackTrans() that a
77 * new wxDB object be created and used for it.
83 * This function will return the exact string(s) from the database engine
84 * indicating all error conditions which have just occured during the
85 * last call to the database engine.
87 * This demo uses the returned string by displaying it in a wxMessageBox. The
88 * formatting therefore is not the greatest, but this is just a demo, not a
89 * finished product. :-) gt
91 * NOTE: The value returned by this function is for temporary use only and
92 * should be copied for long term use
94 char *GetExtendedDBErrorMsg(char *ErrFile
, int ErrLine
)
100 if (ErrFile
|| ErrLine
)
105 tStr
.Printf("%d",ErrLine
);
106 msg
+= tStr
.GetData();
110 msg
.Append ("\nODBC errors:\n");
113 /* Scan through each database connection displaying
114 * any ODBC errors that have occured. */
116 for (pDbList
= PtrBegDbList
; pDbList
; pDbList
= pDbList
->PtrNext
)
118 // Skip over any free connections
121 // Display errors for this connection
123 for (i
= 0; i
< DB_MAX_ERROR_HISTORY
; i
++)
125 if (pDbList
->PtrDb
->errorList
[i
])
127 msg
.Append(pDbList
->PtrDb
->errorList
[i
]);
128 if (strcmp(pDbList
->PtrDb
->errorList
[i
],"") != 0)
135 return (char*) (const char*) msg
;
136 } // GetExtendedDBErrorMsg
139 bool DatabaseDemoApp::OnInit()
141 // Create the main frame window
142 DemoFrame
= new DatabaseDemoFrame(NULL
, "wxWindows Database Demo", wxPoint(50, 50), wxSize(537, 480));
145 DemoFrame
->SetIcon(wxICON(db
));
148 wxMenu
*file_menu
= new wxMenu
;
149 file_menu
->Append(FILE_CREATE
, "&Create contact table");
150 file_menu
->Append(FILE_EXIT
, "E&xit");
152 wxMenu
*edit_menu
= new wxMenu
;
153 edit_menu
->Append(EDIT_PARAMETERS
, "&Parameters...");
155 wxMenu
*about_menu
= new wxMenu
;
156 about_menu
->Append(ABOUT_DEMO
, "&About");
158 wxMenuBar
*menu_bar
= new wxMenuBar
;
159 menu_bar
->Append(file_menu
, "&File");
160 menu_bar
->Append(edit_menu
, "&Edit");
161 menu_bar
->Append(about_menu
, "&About");
162 DemoFrame
->SetMenuBar(menu_bar
);
164 // Initialize the ODBC Environment for Database Operations
165 if (SQLAllocEnv(&DbConnectInf
.Henv
) != SQL_SUCCESS
)
167 wxMessageBox("A problem occured while trying to get a connection to the data source","DB CONNECTION ERROR",wxOK
| wxICON_EXCLAMATION
);
171 params
.ODBCSource
[0] = 0;
172 params
.UserName
[0] = 0;
173 params
.Password
[0] = 0;
174 params
.DirPath
[0] = 0;
177 if ((paramFile
= fopen(paramFilename
, "r")) == NULL
)
180 tStr
.Printf("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.",paramFilename
);
181 wxMessageBox(tStr
,"File I/O Error...",wxOK
| wxICON_EXCLAMATION
);
183 DemoFrame
->BuildParameterDialog(NULL
);
184 if ((paramFile
= fopen(paramFilename
, "r")) == NULL
)
189 fgets(buffer
, sizeof(params
.ODBCSource
), paramFile
);
190 buffer
[strlen(buffer
)-1] = '\0';
191 strcpy(params
.ODBCSource
,buffer
);
193 fgets(buffer
, sizeof(params
.UserName
), paramFile
);
194 buffer
[strlen(buffer
)-1] = '\0';
195 strcpy(params
.UserName
,buffer
);
197 fgets(buffer
, sizeof(params
.Password
), paramFile
);
198 buffer
[strlen(buffer
)-1] = '\0';
199 strcpy(params
.Password
,buffer
);
201 fgets(buffer
, sizeof(params
.DirPath
), paramFile
);
202 buffer
[strlen(buffer
)-1] = '\0';
203 strcpy(params
.DirPath
,buffer
);
207 // Connect to datasource
208 strcpy(DbConnectInf
.Dsn
, params
.ODBCSource
); // ODBC data source name (created with ODBC Administrator under Win95/NT)
209 strcpy(DbConnectInf
.Uid
, params
.UserName
); // database username - must already exist in the data source
210 strcpy(DbConnectInf
.AuthStr
, params
.Password
); // password database username
211 strcpy(DbConnectInf
.defaultDir
, params
.DirPath
); // path where the table exists (needed for dBase)
213 READONLY_DB
= wxDbGetConnection(&DbConnectInf
);
214 if (READONLY_DB
== 0)
216 wxMessageBox("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)", "DB CONNECTION ERROR...",wxOK
| wxICON_EXCLAMATION
);
217 DemoFrame
->BuildParameterDialog(NULL
);
218 strcpy(DbConnectInf
.Dsn
, "");
219 strcpy(DbConnectInf
.Uid
, "");
220 strcpy(DbConnectInf
.AuthStr
, "");
221 wxMessageBox("Now exiting program.\n\nRestart program to try any new settings.","Notice...",wxOK
| wxICON_INFORMATION
);
225 DemoFrame
->BuildEditorDialog();
228 DemoFrame
->Show(TRUE
);
231 } // DatabaseDemoApp::OnInit()
233 BEGIN_EVENT_TABLE(DatabaseDemoFrame
, wxFrame
)
234 EVT_MENU(FILE_CREATE
, DatabaseDemoFrame::OnCreate
)
235 EVT_MENU(FILE_EXIT
, DatabaseDemoFrame::OnExit
)
236 EVT_MENU(EDIT_PARAMETERS
, DatabaseDemoFrame::OnEditParameters
)
237 EVT_MENU(ABOUT_DEMO
, DatabaseDemoFrame::OnAbout
)
238 EVT_CLOSE(DatabaseDemoFrame::OnCloseWindow
)
241 // DatabaseDemoFrame constructor
242 DatabaseDemoFrame::DatabaseDemoFrame(wxFrame
*frame
, const wxString
& title
,
243 const wxPoint
& pos
, const wxSize
& size
):
244 wxFrame(frame
, -1, title
, pos
, size
)
246 // Put any code in necessary for initializing the main frame here
249 void DatabaseDemoFrame::OnCreate(wxCommandEvent
& event
)
254 void DatabaseDemoFrame::OnExit(wxCommandEvent
& event
)
259 void DatabaseDemoFrame::OnEditParameters(wxCommandEvent
& event
)
261 if ((pEditorDlg
->mode
!= mCreate
) && (pEditorDlg
->mode
!= mEdit
))
262 BuildParameterDialog(this);
264 wxMessageBox("Cannot change database parameters while creating or editing a record","Notice...",wxOK
| wxICON_INFORMATION
);
267 void DatabaseDemoFrame::OnAbout(wxCommandEvent
& event
)
269 wxMessageBox("wxWindows sample program for database classes\n\nContributed on 27 July 1998","About...",wxOK
| wxICON_INFORMATION
);
272 void DatabaseDemoFrame::OnCloseWindow(wxCloseEvent
& event
)
274 // Put any additional checking necessary to make certain it is alright
275 // to close the program here that is not done elsewhere
278 if (pEditorDlg
->Close())
285 } // DatabaseDemoFrame::OnCloseWindow()
288 void DatabaseDemoFrame::CreateDataTable()
290 bool Ok
= (wxMessageBox("Any data currently residing in the table will be erased.\n\nAre you sure?","Confirm",wxYES_NO
|wxICON_QUESTION
) == wxYES
);
299 Ccontact
*Contact
= new Ccontact();
303 wxMessageBox("Error allocating memory for 'Ccontact'object.\n\nTable was not created.","Error...",wxOK
| wxICON_EXCLAMATION
);
307 if (!Contact
->CreateTable(FALSE
))
311 tStr
= "Error creating CONTACTS table.\nTable was not created.\n\n";
312 tStr
+= GetExtendedDBErrorMsg(__FILE__
,__LINE__
);
313 wxMessageBox(tStr
,"ODBC Error...",wxOK
| wxICON_EXCLAMATION
);
318 if (!Contact
->CreateIndexes())
322 tStr
= "Error creating CONTACTS indexes.\nIndexes will be unavailable.\n\n";
323 tStr
+= GetExtendedDBErrorMsg(__FILE__
,__LINE__
);
324 wxMessageBox(tStr
,"ODBC Error...",wxOK
| wxICON_EXCLAMATION
);
334 wxMessageBox("Table and index(es) were successfully created.","Notice...",wxOK
| wxICON_INFORMATION
);
335 } // DatabaseDemoFrame::CreateDataTable()
338 void DatabaseDemoFrame::BuildEditorDialog()
340 pEditorDlg
= new CeditorDlg(this);
342 wxMessageBox("Unable to create the editor dialog for some reason","Error...",wxOK
| wxICON_EXCLAMATION
);
343 } // DatabaseDemoFrame::BuildEditorDialog()
346 void DatabaseDemoFrame::BuildParameterDialog(wxWindow
*parent
)
348 pParamDlg
= new CparameterDlg(parent
);
351 wxMessageBox("Unable to create the parameter dialog for some reason","Error...",wxOK
| wxICON_EXCLAMATION
);
352 } // DatabaseDemoFrame::BuildParameterDialog()
356 * Constructor note: If no wxDB object is passed in, a new connection to the database
357 * is created for this instance of Ccontact. This can be a slow process depending
358 * on the database engine being used, and some database engines have a limit on the
359 * number of connections (either hard limits, or license restricted) so care should
360 * be used to use as few connections as is necessary.
362 * IMPORTANT: Objects which share a wxDB pointer are ALL acted upon whenever a member
363 * function of pDb is called (i.e. CommitTrans() or RollbackTrans(), so if modifying
364 * or creating a table objects which use the same pDb, know that all the objects
365 * will be committed or rolled back when any of the objects has this function call made.
367 Ccontact::Ccontact (wxDB
*pwxDB
) : wxTable(pwxDB
? pwxDB
: wxDbGetConnection(&DbConnectInf
),CONTACT_TABLE_NAME
,CONTACT_NO_COLS
,NULL
,!QUERY_ONLY
,DbConnectInf
.defaultDir
)
369 // This is used to represent whether the database connection should be released
370 // when this instance of the object is deleted. If using the same connection
371 // for multiple instance of database objects, then the connection should only be
372 // released when the last database instance using the connection is deleted
377 } // Ccontact Constructor
380 void Ccontact::Initialize()
389 JoinDate
.year
= 1980;
395 JoinDate
.fraction
= 0;
396 NativeLanguage
= langENGLISH
;
400 } // Ccontact::Initialize
403 Ccontact::~Ccontact()
407 if (!wxDbFreeConnection(pDb
))
410 tStr
= "Unable to Free the Ccontact data table handle\n\n";
411 tStr
+= GetExtendedDBErrorMsg(__FILE__
,__LINE__
);
412 wxMessageBox(tStr
,"ODBC Error...",wxOK
| wxICON_EXCLAMATION
);
415 } // Ccontract destructor
419 * Handles setting up all the connections for the interface from the wxTable
420 * functions to interface to the data structure used to store records in
421 * memory, and for all the column definitions that define the table structure
423 void Ccontact::SetupColumns()
425 // NOTE: Columns now are 8 character names, as that is all dBase can support. Longer
426 // names can be used for other database engines
427 SetColDefs ( 0,"NAME", DB_DATA_TYPE_VARCHAR
, Name
, SQL_C_CHAR
, sizeof(Name
), TRUE
, TRUE
); // Primary index
428 SetColDefs ( 1,"ADDRESS1", DB_DATA_TYPE_VARCHAR
, Addr1
, SQL_C_CHAR
, sizeof(Addr1
), FALSE
,TRUE
);
429 SetColDefs ( 2,"ADDRESS2", DB_DATA_TYPE_VARCHAR
, Addr2
, SQL_C_CHAR
, sizeof(Addr2
), FALSE
,TRUE
);
430 SetColDefs ( 3,"CITY", DB_DATA_TYPE_VARCHAR
, City
, SQL_C_CHAR
, sizeof(City
), FALSE
,TRUE
);
431 SetColDefs ( 4,"STATE", DB_DATA_TYPE_VARCHAR
, State
, SQL_C_CHAR
, sizeof(State
), FALSE
,TRUE
);
432 SetColDefs ( 5,"POSTCODE", DB_DATA_TYPE_VARCHAR
, PostalCode
, SQL_C_CHAR
, sizeof(PostalCode
), FALSE
,TRUE
);
433 SetColDefs ( 6,"COUNTRY", DB_DATA_TYPE_VARCHAR
, Country
, SQL_C_CHAR
, sizeof(Country
), FALSE
,TRUE
);
434 SetColDefs ( 7,"JOINDATE", DB_DATA_TYPE_DATE
, &JoinDate
, SQL_C_TIMESTAMP
, sizeof(JoinDate
), FALSE
,TRUE
);
435 SetColDefs ( 8,"IS_DEV", DB_DATA_TYPE_INTEGER
, &IsDeveloper
, SQL_C_BOOLEAN(IsDeveloper
), sizeof(IsDeveloper
), FALSE
,TRUE
);
436 SetColDefs ( 9,"CONTRIBS", DB_DATA_TYPE_INTEGER
, &Contributions
, SQL_C_USHORT
, sizeof(Contributions
), FALSE
,TRUE
);
437 SetColDefs (10,"LINE_CNT", DB_DATA_TYPE_INTEGER
, &LinesOfCode
, SQL_C_ULONG
, sizeof(LinesOfCode
), FALSE
,TRUE
);
438 SetColDefs (11,"LANGUAGE", DB_DATA_TYPE_INTEGER
, &NativeLanguage
, SQL_C_ENUM
, sizeof(NativeLanguage
), FALSE
,TRUE
);
439 } // Ccontact::SetupColumns
442 bool Ccontact::CreateIndexes(void)
444 // This index could easily be accomplished with an "orderBy" clause,
445 // but is done to show how to construct a non-primary index.
451 strcpy(idxDef
[0].ColName
, "IS_DEV");
452 idxDef
[0].Ascending
= TRUE
;
454 strcpy(idxDef
[1].ColName
, "NAME");
455 idxDef
[1].Ascending
= TRUE
;
457 indexName
= CONTACT_TABLE_NAME
;
458 indexName
+= "_IDX1";
459 Ok
= CreateIndex((char*) (const char*) indexName
, TRUE
, 2, idxDef
);
462 } // Ccontact::CreateIndexes()
466 * Having a function to do a query on the primary key (and possibly others) is
467 * very efficient and tighter coding so that it is available where ever the object
468 * is. Great for use with multiple tables when not using views or outer joins
470 bool Ccontact::FetchByName(char *name
)
472 whereStr
.Printf("NAME = '%s'",name
);
473 where
= (char*) (const char*) this->whereStr
;
482 } // Ccontact::FetchByName()
487 * ************* DIALOGS ***************
492 /* CeditorDlg constructor
494 * Creates the dialog used for creating/editing/deleting/copying a Ccontact object.
495 * This dialog actually is drawn in the main frame of the program
497 * An instance of Ccontact is created - "Contact" - which is used to hold the Ccontact
498 * object that is currently being worked with.
501 BEGIN_EVENT_TABLE(CeditorDlg
, wxPanel
)
502 EVT_BUTTON(-1, CeditorDlg::OnButton
)
503 EVT_CLOSE(CeditorDlg::OnCloseWindow
)
506 CeditorDlg::CeditorDlg(wxWindow
*parent
) : wxPanel (parent
, 1, 1, 460, 455)
508 // Since the ::OnCommand() function is overridden, this prevents the widget
509 // detection in ::OnCommand() until all widgets have been initialized to prevent
510 // uninitialized pointers from crashing the program
511 widgetPtrsSet
= FALSE
;
513 // Create the data structure and a new database connection.
514 // (As there is not a pDb being passed in the constructor, a new database
515 // connection is created)
516 Contact
= new Ccontact();
520 wxMessageBox("Unable to instantiate an instance of Ccontact","Error...",wxOK
| wxICON_EXCLAMATION
);
524 // Check if the table exists or not. If it doesn't, ask the user if they want to
525 // create the table. Continue trying to create the table until it exists, or user aborts
526 while (!Contact
->pDb
->TableExists((char *)CONTACT_TABLE_NAME
,DbConnectInf
.Uid
,DbConnectInf
.defaultDir
))
529 tStr
.Printf("Unable to open the table '%s'.\n\nTable may need to be created...?\n\n",CONTACT_TABLE_NAME
);
530 tStr
+= GetExtendedDBErrorMsg(__FILE__
,__LINE__
);
531 wxMessageBox(tStr
,"ODBC Error...",wxOK
| wxICON_EXCLAMATION
);
533 bool createTable
= (wxMessageBox("Do you wish to try to create/clear the CONTACTS table?","Confirm",wxYES_NO
|wxICON_QUESTION
) == wxYES
);
543 DemoFrame
->CreateDataTable();
546 // Tables must be "opened" before anything other than creating/deleting table can be done
547 if (!Contact
->Open())
549 // Table does exist, there was some problem opening it. Currently this should
550 // never fail, except in the case of the table not exisiting. Open() basically
551 // only sets up variable/pointer values, other than checking for table existence.
552 if (Contact
->pDb
->TableExists((char *)CONTACT_TABLE_NAME
))
555 tStr
.Printf("Unable to open the table '%s'.\n\n",CONTACT_TABLE_NAME
);
556 tStr
+= GetExtendedDBErrorMsg(__FILE__
,__LINE__
);
557 wxMessageBox(tStr
,"ODBC Error...",wxOK
| wxICON_EXCLAMATION
);
567 (void)new wxStaticBox(this, EDITOR_DIALOG_FN_GROUP
, "", wxPoint(15, 1), wxSize(497, 69), 0, "FunctionGrp");
568 (void)new wxStaticBox(this, EDITOR_DIALOG_SEARCH_GROUP
, "", wxPoint(417, 1), wxSize(95, 242), 0, "SearchGrp");
570 pCreateBtn
= new wxButton(this, EDITOR_DIALOG_CREATE
, "&Create", wxPoint( 25, 21), wxSize( 70, 35), 0, wxDefaultValidator
, "CreateBtn");
571 pEditBtn
= new wxButton(this, EDITOR_DIALOG_EDIT
, "&Edit", wxPoint(102, 21), wxSize( 70, 35), 0, wxDefaultValidator
, "EditBtn");
572 pDeleteBtn
= new wxButton(this, EDITOR_DIALOG_DELETE
, "&Delete", wxPoint(179, 21), wxSize( 70, 35), 0, wxDefaultValidator
, "DeleteBtn");
573 pCopyBtn
= new wxButton(this, EDITOR_DIALOG_COPY
, "Cop&y", wxPoint(256, 21), wxSize( 70, 35), 0, wxDefaultValidator
, "CopyBtn");
574 pSaveBtn
= new wxButton(this, EDITOR_DIALOG_SAVE
, "&Save", wxPoint(333, 21), wxSize( 70, 35), 0, wxDefaultValidator
, "SaveBtn");
575 pCancelBtn
= new wxButton(this, EDITOR_DIALOG_CANCEL
, "C&ancel", wxPoint(430, 21), wxSize( 70, 35), 0, wxDefaultValidator
, "CancelBtn");
576 pPrevBtn
= new wxButton(this, EDITOR_DIALOG_PREV
, "<< &Prev", wxPoint(430, 81), wxSize( 70, 35), 0, wxDefaultValidator
, "PrevBtn");
577 pNextBtn
= new wxButton(this, EDITOR_DIALOG_NEXT
, "&Next >>", wxPoint(430, 121), wxSize( 70, 35), 0, wxDefaultValidator
, "NextBtn");
578 pQueryBtn
= new wxButton(this, EDITOR_DIALOG_QUERY
, "&Query", wxPoint(430, 161), wxSize( 70, 35), 0, wxDefaultValidator
, "QueryBtn");
579 pResetBtn
= new wxButton(this, EDITOR_DIALOG_RESET
, "&Reset", wxPoint(430, 200), wxSize( 70, 35), 0, wxDefaultValidator
, "ResetBtn");
580 pNameMsg
= new wxStaticText(this, EDITOR_DIALOG_NAME_MSG
, "Name:", wxPoint( 17, 80), wxSize( -1, -1), 0, "NameMsg");
581 pNameTxt
= new wxTextCtrl(this, EDITOR_DIALOG_NAME_TEXT
, "", wxPoint( 17, 97), wxSize(308, 25), 0, wxDefaultValidator
, "NameTxt");
582 pNameListBtn
= new wxButton(this, EDITOR_DIALOG_LOOKUP
, "&Lookup", wxPoint(333, 97), wxSize( 70, 24), 0, wxDefaultValidator
, "LookupBtn");
583 pAddress1Msg
= new wxStaticText(this, EDITOR_DIALOG_ADDRESS1_MSG
, "Address:", wxPoint( 17, 130), wxSize( -1, -1), 0, "Address1Msg");
584 pAddress1Txt
= new wxTextCtrl(this, EDITOR_DIALOG_ADDRESS2_TEXT
, "", wxPoint( 17, 147), wxSize(308, 25), 0, wxDefaultValidator
, "Address1Txt");
585 pAddress2Msg
= new wxStaticText(this, EDITOR_DIALOG_ADDRESS2_MSG
, "Address:", wxPoint( 17, 180), wxSize( -1, -1), 0, "Address2Msg");
586 pAddress2Txt
= new wxTextCtrl(this, EDITOR_DIALOG_ADDRESS2_TEXT
, "", wxPoint( 17, 197), wxSize(308, 25), 0, wxDefaultValidator
, "Address2Txt");
587 pCityMsg
= new wxStaticText(this, EDITOR_DIALOG_CITY_MSG
, "City:", wxPoint( 17, 230), wxSize( -1, -1), 0, "CityMsg");
588 pCityTxt
= new wxTextCtrl(this, EDITOR_DIALOG_CITY_TEXT
, "", wxPoint( 17, 247), wxSize(225, 25), 0, wxDefaultValidator
, "CityTxt");
589 pStateMsg
= new wxStaticText(this, EDITOR_DIALOG_STATE_MSG
, "State:", wxPoint(250, 230), wxSize( -1, -1), 0, "StateMsg");
590 pStateTxt
= new wxTextCtrl(this, EDITOR_DIALOG_STATE_TEXT
, "", wxPoint(250, 247), wxSize(153, 25), 0, wxDefaultValidator
, "StateTxt");
591 pCountryMsg
= new wxStaticText(this, EDITOR_DIALOG_COUNTRY_MSG
, "Country:", wxPoint( 17, 280), wxSize( -1, -1), 0, "CountryMsg");
592 pCountryTxt
= new wxTextCtrl(this, EDITOR_DIALOG_COUNTRY_TEXT
, "", wxPoint( 17, 297), wxSize(225, 25), 0, wxDefaultValidator
, "CountryTxt");
593 pPostalCodeMsg
= new wxStaticText(this, EDITOR_DIALOG_POSTAL_MSG
, "Postal Code:",wxPoint(250, 280), wxSize( -1, -1), 0, "PostalCodeMsg");
594 pPostalCodeTxt
= new wxTextCtrl(this, EDITOR_DIALOG_POSTAL_TEXT
, "", wxPoint(250, 297), wxSize(153, 25), 0, wxDefaultValidator
, "PostalCodeTxt");
596 wxString choice_strings
[5];
597 choice_strings
[0] = "English";
598 choice_strings
[1] = "French";
599 choice_strings
[2] = "German";
600 choice_strings
[3] = "Spanish";
601 choice_strings
[4] = "Other";
603 pNativeLangChoice
= new wxChoice(this, EDITOR_DIALOG_LANG_CHOICE
, wxPoint( 17, 346), wxSize(277, -1), 5, choice_strings
);
604 pNativeLangMsg
= new wxStaticText(this, EDITOR_DIALOG_LANG_MSG
, "Native language:", wxPoint( 17, 330), wxSize( -1, -1), 0, "NativeLangMsg");
606 wxString radio_strings
[2];
607 radio_strings
[0] = "No";
608 radio_strings
[1] = "Yes";
609 pDeveloperRadio
= new wxRadioBox(this,EDITOR_DIALOG_DEVELOPER
, "Developer:", wxPoint(303, 330), wxSize( -1, -1), 2, radio_strings
, 2, wxHORIZONTAL
);
610 pJoinDateMsg
= new wxStaticText(this, EDITOR_DIALOG_JOIN_MSG
, "Date joined:", wxPoint( 17, 380), wxSize( -1, -1), 0, "JoinDateMsg");
611 pJoinDateTxt
= new wxTextCtrl(this, EDITOR_DIALOG_JOIN_TEXT
, "", wxPoint( 17, 397), wxSize(150, 25), 0, wxDefaultValidator
, "JoinDateTxt");
612 pContribMsg
= new wxStaticText(this, EDITOR_DIALOG_CONTRIB_MSG
,"Contributions:", wxPoint(175, 380), wxSize( -1, -1), 0, "ContribMsg");
613 pContribTxt
= new wxTextCtrl(this, EDITOR_DIALOG_CONTRIB_TEXT
, "", wxPoint(175, 397), wxSize(120, 25), 0, wxDefaultValidator
, "ContribTxt");
614 pLinesMsg
= new wxStaticText(this, EDITOR_DIALOG_LINES_MSG
, "Lines of code:", wxPoint(303, 380), wxSize( -1, -1), 0, "LinesMsg");
615 pLinesTxt
= new wxTextCtrl(this, EDITOR_DIALOG_LINES_TEXT
, "", wxPoint(303, 397), wxSize(100, 25), 0, wxDefaultValidator
, "LinesTxt");
617 // Now that all the widgets on the panel are created, its safe to allow ::OnCommand() to
618 // handle all widget processing
619 widgetPtrsSet
= TRUE
;
621 // Setup the orderBy and where clauses to return back a single record as the result set,
622 // as there will only be one record being shown on the dialog at a time, this optimizes
623 // network traffic by only returning a one row result
625 Contact
->orderBy
= "NAME"; // field name to sort by
627 // The wxString "whereStr" is not a member of the wxTable object, it is a member variable
628 // specifically in the Ccontact class. It is used here for simpler construction of a varying
629 // length string, and then after the string is built, the wxTable member variable "where" is
630 // assigned the pointer to the constructed string.
632 // The constructed where clause below has a sub-query within it "SELECT MIN(NAME) FROM %s"
633 // to achieve a single row (in this case the first name in alphabetical order).
635 if (Contact
->pDb
->Dbms() != dbmsPOSTGRES
)
637 Contact
->whereStr
.sprintf("NAME = (SELECT MIN(NAME) FROM %s)",Contact
->tableName
);
638 // NOTE: (const char*) returns a pointer which may not be valid later, so this is short term use only
639 Contact
->where
= (char*) (const char*) Contact
->whereStr
;
644 // Perform the Query to get the result set.
645 // NOTE: If there are no rows returned, that is a valid result, so Query() would return TRUE.
646 // Only if there is a database error will Query() come back as FALSE
647 if (!Contact
->Query())
650 tStr
= "ODBC error during Query()\n\n";
651 tStr
+= GetExtendedDBErrorMsg(__FILE__
,__LINE__
);
652 wxMessageBox(tStr
,"ODBC Error...",wxOK
| wxICON_EXCLAMATION
);
653 GetParent()->Close();
657 // Since Query succeeded, now get the row that was returned
658 if (!Contact
->GetNext())
659 // If the GetNext() failed at this point, then there are no rows to retrieve,
660 // so clear the values in the members of "Contact" so that PutData() blanks the
661 // widgets on the dialog
662 Contact
->Initialize();
668 } // CeditorDlg constructor
671 void CeditorDlg::OnCloseWindow(wxCloseEvent
& event
)
674 if ((mode
!= mCreate
) && (mode
!= mEdit
))
682 wxMessageBox("Must finish processing the current record being created/modified before exiting","Notice...",wxOK
| wxICON_INFORMATION
);
685 } // CeditorDlg::OnCloseWindow()
688 void CeditorDlg::OnButton( wxCommandEvent
&event
)
690 wxWindow
*win
= (wxWindow
*) event
.GetEventObject();
691 OnCommand( *win
, event
);
695 void CeditorDlg::OnCommand(wxWindow
& win
, wxCommandEvent
& event
)
699 widgetName
= win
.GetName();
704 if (widgetName
== pCreateBtn
->GetName())
706 Contact
->Initialize();
709 pNameTxt
->SetValue("");
710 pNameTxt
->SetFocus();
714 if (widgetName
== pEditBtn
->GetName())
716 saveName
= Contact
->Name
;
718 pNameTxt
->SetFocus();
722 if (widgetName
== pCopyBtn
->GetName())
725 pNameTxt
->SetValue("");
726 pNameTxt
->SetFocus();
731 if (widgetName
== pDeleteBtn
->GetName())
733 bool Ok
= (wxMessageBox("Are you sure?","Confirm",wxYES_NO
|wxICON_QUESTION
) == wxYES
);
738 if (Ok
&& Contact
->Delete())
740 // NOTE: Deletions are not finalized until a CommitTrans() is performed.
741 // If the commit were not performed, the program will continue to
742 // show the table contents as if they were deleted until this instance
743 // of Ccontact is deleted. If the Commit wasn't performed, the
744 // database will automatically Rollback the changes when the database
745 // connection is terminated
746 Contact
->pDb
->CommitTrans();
748 // Try to get the row that followed the just deleted row in the orderBy sequence
751 // There was now row (in sequence) after the just deleted row, so get the
752 // row which preceded the just deleted row
755 // There are now no rows remaining, so clear the dialog widgets
756 Contact
->Initialize();
760 SetMode(mode
); // force reset of button enable/disable
764 Contact
->pDb
->RollbackTrans();
770 if (widgetName
== pSaveBtn
->GetName())
776 if (widgetName
== pCancelBtn
->GetName())
778 bool Ok
= (wxMessageBox("Are you sure?","Confirm",wxYES_NO
|wxICON_QUESTION
) == wxYES
);
783 if (!strcmp((const char*) saveName
,""))
785 Contact
->Initialize();
792 // Requery previous record
793 if (Contact
->FetchByName((char*) (const char*) saveName
))
801 // Previous record not available, retrieve first record in table
802 if (Contact
->pDb
->Dbms() != dbmsPOSTGRES
)
804 Contact
->whereStr
= "NAME = (SELECT MIN(NAME) FROM ";
805 Contact
->whereStr
+= Contact
->tableName
;
806 Contact
->whereStr
+= ")";
807 Contact
->where
= (char*) (const char*) Contact
->whereStr
;
812 if (!Contact
->Query())
815 tStr
= "ODBC error during Query()\n\n";
816 tStr
+= GetExtendedDBErrorMsg(__FILE__
,__LINE__
);
817 wxMessageBox(tStr
,"ODBC Error...",wxOK
| wxICON_EXCLAMATION
);
821 if (Contact
->GetNext()) // Successfully read first record
827 // No contacts are available, clear dialog
828 Contact
->Initialize();
834 if (widgetName
== pPrevBtn
->GetName())
841 if (widgetName
== pNextBtn
->GetName())
848 if (widgetName
== pQueryBtn
->GetName())
850 // Display the query dialog box
851 char qryWhere
[DB_MAX_WHERE_CLAUSE_LEN
+1];
852 strcpy(qryWhere
, (const char*) Contact
->qryWhereStr
);
853 char *tblName
[] = {(char *)CONTACT_TABLE_NAME
, 0};
854 new CqueryDlg(GetParent(), Contact
->pDb
, tblName
, qryWhere
);
856 // Query the first record in the new record set and
857 // display it, if the query string has changed.
858 if (strcmp(qryWhere
, (const char*) Contact
->qryWhereStr
))
861 Contact
->whereStr
= "";
862 Contact
->orderBy
= "NAME";
864 if (Contact
->pDb
->Dbms() != dbmsPOSTGRES
)
866 Contact
->whereStr
= "NAME = (SELECT MIN(NAME) FROM ";
867 Contact
->whereStr
+= CONTACT_TABLE_NAME
;
870 // Append the query where string (if there is one)
871 Contact
->qryWhereStr
= qryWhere
;
872 if (strlen(qryWhere
))
874 Contact
->whereStr
+= " WHERE ";
875 Contact
->whereStr
+= Contact
->qryWhereStr
;
877 // Close the expression with a right paren
878 Contact
->whereStr
+= ")";
880 Contact
->where
= (char*) (const char*) Contact
->whereStr
;
881 if (!Contact
->Query())
884 tStr
= "ODBC error during Query()\n\n";
885 tStr
+= GetExtendedDBErrorMsg(__FILE__
,__LINE__
);
886 wxMessageBox(tStr
,"ODBC Error...",wxOK
| wxICON_EXCLAMATION
);
889 // Display the first record from the query set
890 if (!Contact
->GetNext())
891 Contact
->Initialize();
895 // Enable/Disable the reset button
896 pResetBtn
->Enable(!Contact
->qryWhereStr
.IsEmpty());
902 if (widgetName
== pResetBtn
->GetName())
904 // Clear the additional where criteria established by the query feature
905 Contact
->qryWhereStr
= "";
906 Contact
->orderBy
= "NAME";
908 if (Contact
->pDb
->Dbms() != dbmsPOSTGRES
)
910 Contact
->whereStr
= "NAME = (SELECT MIN(NAME) FROM ";
911 Contact
->whereStr
+= CONTACT_TABLE_NAME
;
912 Contact
->whereStr
+= ")";
915 Contact
->where
= (char*) (const char*) Contact
->whereStr
;
916 if (!Contact
->Query())
919 tStr
= "ODBC error during Query()\n\n";
920 tStr
+= GetExtendedDBErrorMsg(__FILE__
,__LINE__
);
921 wxMessageBox(tStr
,"ODBC Error...",wxOK
| wxICON_EXCLAMATION
);
924 if (!Contact
->GetNext())
925 Contact
->Initialize();
927 pResetBtn
->Enable(FALSE
);
933 if (widgetName
== pNameListBtn
->GetName())
935 new ClookUpDlg(/* wxWindow *parent */ this,
936 /* char *windowTitle */ "Select contact name",
937 /* char *tableName */ (char *) CONTACT_TABLE_NAME
,
938 /* char *dispCol1 */ "NAME",
939 /* char *dispCol2 */ "JOINDATE",
940 /* char *where */ "",
941 /* char *orderBy */ "NAME",
942 /* bool distinctValues */ TRUE
);
944 if (ListDB_Selection
&& strlen(ListDB_Selection
))
946 wxString w
= "NAME = '";
947 w
+= ListDB_Selection
;
949 GetRec((char*) (const char*) w
);
955 } // CeditorDlg::OnCommand()
958 void CeditorDlg::FieldsEditable()
960 pNameTxt
->Enable((mode
== mCreate
) || (mode
== mEdit
));
961 pAddress1Txt
->Enable((mode
== mCreate
) || (mode
== mEdit
));
962 pAddress2Txt
->Enable((mode
== mCreate
) || (mode
== mEdit
));
963 pCityTxt
->Enable((mode
== mCreate
) || (mode
== mEdit
));
964 pStateTxt
->Enable((mode
== mCreate
) || (mode
== mEdit
));
965 pPostalCodeTxt
->Enable((mode
== mCreate
) || (mode
== mEdit
));
966 pCountryTxt
->Enable((mode
== mCreate
) || (mode
== mEdit
));
968 pJoinDateTxt
->Enable((mode
== mCreate
) || (mode
== mEdit
));
969 pContribTxt
->Enable((mode
== mCreate
) || (mode
== mEdit
));
970 pLinesTxt
->Enable((mode
== mCreate
) || (mode
== mEdit
));
971 pNativeLangChoice
->Enable((mode
== mCreate
) || (mode
== mEdit
));
972 pDeveloperRadio
->Enable((mode
== mCreate
) || (mode
== mEdit
));
974 } // CeditorDlg::FieldsEditable()
977 void CeditorDlg::SetMode(enum DialogModes m
)
998 pCreateBtn
->Enable( !edit
);
999 pEditBtn
->Enable( !edit
&& (strcmp(Contact
->Name
,"")!=0) );
1000 pDeleteBtn
->Enable( !edit
&& (strcmp(Contact
->Name
,"")!=0) );
1001 pCopyBtn
->Enable( !edit
&& (strcmp(Contact
->Name
,"")!=0) );
1002 pSaveBtn
->Enable( edit
);
1003 pCancelBtn
->Enable( edit
);
1004 pPrevBtn
->Enable( !edit
);
1005 pNextBtn
->Enable( !edit
);
1006 pQueryBtn
->Enable( !edit
);
1007 pResetBtn
->Enable( !edit
&& !Contact
->qryWhereStr
.IsEmpty() );
1008 pNameListBtn
->Enable( !edit
);
1012 } // CeditorDlg::SetMode()
1015 bool CeditorDlg::PutData()
1019 pNameTxt
->SetValue(Contact
->Name
);
1020 pAddress1Txt
->SetValue(Contact
->Addr1
);
1021 pAddress2Txt
->SetValue(Contact
->Addr2
);
1022 pCityTxt
->SetValue(Contact
->City
);
1023 pStateTxt
->SetValue(Contact
->State
);
1024 pCountryTxt
->SetValue(Contact
->Country
);
1025 pPostalCodeTxt
->SetValue(Contact
->PostalCode
);
1027 tStr
.Printf("%d/%d/%d",Contact
->JoinDate
.month
,Contact
->JoinDate
.day
,Contact
->JoinDate
.year
);
1028 pJoinDateTxt
->SetValue(tStr
);
1030 tStr
.Printf("%d",Contact
->Contributions
);
1031 pContribTxt
->SetValue(tStr
);
1033 tStr
.Printf("%lu",Contact
->LinesOfCode
);
1034 pLinesTxt
->SetValue(tStr
);
1036 pNativeLangChoice
->SetSelection(Contact
->NativeLanguage
);
1038 pDeveloperRadio
->SetSelection(Contact
->IsDeveloper
);
1041 } // Ceditor::PutData()
1045 * Reads the data out of all the widgets on the dialog. Some data evaluation is done
1046 * to ensure that there is a name entered and that the date field is valid.
1048 * A return value of TRUE means that valid data was retrieved from the dialog, otherwise
1049 * invalid data was found (and a message was displayed telling the user what to fix), and
1050 * the data was not placed into the appropraite fields of Ccontact
1052 bool CeditorDlg::GetData()
1054 // Validate that the data currently entered into the widgets is valid data
1057 tStr
= pNameTxt
->GetValue();
1058 if (!strcmp((const char*) tStr
,""))
1060 wxMessageBox("A name is required for entry into the contact table","Notice...",wxOK
| wxICON_INFORMATION
);
1064 bool invalid
= FALSE
;
1068 tStr
= pJoinDateTxt
->GetValue();
1069 if (tStr
.Freq('/') != 2)
1072 // Find the month, day, and year tokens
1075 first
= tStr
.First('/');
1076 second
= tStr
.Last('/');
1078 mm
= atoi(tStr
.SubString(0,first
));
1079 dd
= atoi(tStr
.SubString(first
+1,second
));
1080 yyyy
= atoi(tStr
.SubString(second
+1,tStr
.Length()-1));
1082 invalid
= !(mm
&& dd
&& yyyy
);
1085 // Force Year 2000 compliance
1086 if (!invalid
&& (yyyy
< 1000))
1089 // Check the token ranges for validity
1094 else if ((mm
< 1) || (mm
> 12))
1102 int days
[12] = {31,28,31,30,31,30,
1104 if (dd
> days
[mm
-1])
1107 if ((dd
== 29) && (mm
== 2))
1109 if (((yyyy
% 4) == 0) && (((yyyy
% 100) != 0) || ((yyyy
% 400) == 0)))
1119 Contact
->JoinDate
.month
= mm
;
1120 Contact
->JoinDate
.day
= dd
;
1121 Contact
->JoinDate
.year
= yyyy
;
1125 wxMessageBox("Improper date format. Please check the date\nspecified and try again.\n\nNOTE: Dates are in american format (MM/DD/YYYY)","Notice...",wxOK
| wxICON_INFORMATION
);
1129 tStr
= pNameTxt
->GetValue();
1130 strcpy(Contact
->Name
,(const char*) tStr
);
1131 strcpy(Contact
->Addr1
,pAddress1Txt
->GetValue());
1132 strcpy(Contact
->Addr2
,pAddress2Txt
->GetValue());
1133 strcpy(Contact
->City
,pCityTxt
->GetValue());
1134 strcpy(Contact
->State
,pStateTxt
->GetValue());
1135 strcpy(Contact
->Country
,pCountryTxt
->GetValue());
1136 strcpy(Contact
->PostalCode
,pPostalCodeTxt
->GetValue());
1138 Contact
->Contributions
= atoi(pContribTxt
->GetValue());
1139 Contact
->LinesOfCode
= atol(pLinesTxt
->GetValue());
1141 Contact
->NativeLanguage
= (enum Language
) pNativeLangChoice
->GetSelection();
1142 Contact
->IsDeveloper
= pDeveloperRadio
->GetSelection() > 0;
1145 } // CeditorDlg::GetData()
1149 * Retrieve data from the dialog, verify the validity of the data, and if it is valid,
1150 * try to insert/update the data to the table based on the current 'mode' the dialog
1153 * A return value of TRUE means the insert/update was completed successfully, a return
1154 * value of FALSE means that Save() failed. If returning FALSE, then this function
1155 * has displayed a detailed error message for the user.
1157 bool CeditorDlg::Save()
1159 bool failed
= FALSE
;
1161 // Read the data in the widgets of the dialog to get the user's data
1165 // Perform any other required validations necessary before saving
1168 wxBeginBusyCursor();
1170 if (mode
== mCreate
)
1172 RETCODE result
= Contact
->Insert();
1174 failed
= (result
!= DB_SUCCESS
);
1177 // Some errors may be expected, like a duplicate key, so handle those instances with
1178 // specific error messages.
1179 if (result
== DB_ERR_INTEGRITY_CONSTRAINT_VIOL
)
1182 tStr
= "A duplicate key value already exists in the table.\nUnable to save record\n\n";
1183 tStr
+= GetExtendedDBErrorMsg(__FILE__
,__LINE__
);
1184 wxMessageBox(tStr
,"ODBC Error...",wxOK
| wxICON_EXCLAMATION
);
1188 // Some other unexpexted error occurred
1190 tStr
= "Database insert failed\n\n";
1191 tStr
+= GetExtendedDBErrorMsg(__FILE__
,__LINE__
);
1192 wxMessageBox(tStr
,"ODBC Error...",wxOK
| wxICON_EXCLAMATION
);
1196 else // mode == mEdit
1198 if (!Contact
->Update())
1201 tStr
= "Database update failed\n\n";
1202 tStr
+= GetExtendedDBErrorMsg(__FILE__
,__LINE__
);
1203 wxMessageBox(tStr
,"ODBC Error...",wxOK
| wxICON_EXCLAMATION
);
1210 Contact
->pDb
->CommitTrans();
1211 SetMode(mView
); // Sets the dialog mode back to viewing after save is successful
1214 Contact
->pDb
->RollbackTrans();
1220 } // CeditorDlg::Save()
1224 * Where this program is only showing a single row at a time in the dialog,
1225 * a special where clause must be built to find just the single row which,
1226 * in sequence, would follow the currently displayed row.
1228 bool CeditorDlg::GetNextRec()
1232 if (Contact
->pDb
->Dbms() != dbmsPOSTGRES
)
1234 w
= "NAME = (SELECT MIN(NAME) FROM ";
1235 w
+= Contact
->tableName
;
1236 w
+= " WHERE NAME > '";
1244 // If a query where string is currently set, append that criteria
1245 if (!Contact
->qryWhereStr
.IsEmpty())
1248 w
+= Contact
->qryWhereStr
;
1253 return(GetRec((char*) (const char*) w
));
1255 } // CeditorDlg::GetNextRec()
1259 * Where this program is only showing a single row at a time in the dialog,
1260 * a special where clause must be built to find just the single row which,
1261 * in sequence, would precede the currently displayed row.
1263 bool CeditorDlg::GetPrevRec()
1267 if (Contact
->pDb
->Dbms() != dbmsPOSTGRES
)
1269 w
= "NAME = (SELECT MAX(NAME) FROM ";
1270 w
+= Contact
->tableName
;
1271 w
+= " WHERE NAME < '";
1279 // If a query where string is currently set, append that criteria
1280 if (!Contact
->qryWhereStr
.IsEmpty())
1283 w
+= Contact
->qryWhereStr
;
1289 return(GetRec((char*) (const char*)w
));
1291 } // CeditorDlg::GetPrevRec()
1295 * This function is here to avoid duplicating this same code in both the
1296 * GetPrevRec() and GetNextRec() functions
1298 bool CeditorDlg::GetRec(char *whereStr
)
1300 Contact
->where
= whereStr
;
1301 Contact
->orderBy
= "NAME";
1303 if (!Contact
->Query())
1306 tStr
= "ODBC error during Query()\n\n";
1307 tStr
+= GetExtendedDBErrorMsg(__FILE__
,__LINE__
);
1308 wxMessageBox(tStr
,"ODBC Error...",wxOK
| wxICON_EXCLAMATION
);
1313 if (Contact
->GetNext())
1320 } // CeditorDlg::GetRec()
1325 * CparameterDlg constructor
1328 BEGIN_EVENT_TABLE(CparameterDlg
, wxDialog
)
1329 EVT_BUTTON(PARAMETER_DIALOG_SAVE
, CparameterDlg::OnButton
)
1330 EVT_BUTTON(PARAMETER_DIALOG_CANCEL
, CparameterDlg::OnButton
)
1331 EVT_CLOSE(CparameterDlg::OnCloseWindow
)
1334 CparameterDlg::CparameterDlg(wxWindow
*parent
) : wxDialog (parent
, PARAMETER_DIALOG
, "ODBC parameter settings", wxPoint(-1, -1), wxSize(400, 325))
1336 // Since the ::OnCommand() function is overridden, this prevents the widget
1337 // detection in ::OnCommand() until all widgets have been initialized to prevent
1338 // uninitialized pointers from crashing the program
1339 widgetPtrsSet
= FALSE
;
1341 pParamODBCSourceMsg
= new wxStaticText(this, PARAMETER_DIALOG_SOURCE_MSG
, "ODBC data sources:", wxPoint( 10, 10), wxSize( -1, -1), 0, "ParamODBCSourceMsg");
1342 pParamODBCSourceList
= new wxListBox(this, PARAMETER_DIALOG_SOURCE_LISTBOX
, wxPoint( 10, 29), wxSize(285, 150), 0, 0, wxLB_SINGLE
|wxLB_ALWAYS_SB
, wxDefaultValidator
, "ParamODBCSourceList");
1343 pParamUserNameMsg
= new wxStaticText(this, PARAMETER_DIALOG_NAME_MSG
, "Database user name:", wxPoint( 10, 193), wxSize( -1, -1), 0, "ParamUserNameMsg");
1344 pParamUserNameTxt
= new wxTextCtrl(this, PARAMETER_DIALOG_NAME_TEXT
, "", wxPoint(10, 209), wxSize( 140, 25), 0, wxDefaultValidator
, "ParamUserNameTxt");
1345 pParamPasswordMsg
= new wxStaticText(this, PARAMETER_DIALOG_PASSWORD_MSG
, "Password:", wxPoint(156, 193), wxSize( -1, -1), 0, "ParamPasswordMsg");
1346 pParamPasswordTxt
= new wxTextCtrl(this, PARAMETER_DIALOG_PASSWORD_TEXT
, "", wxPoint(156, 209), wxSize( 140, 25), 0, wxDefaultValidator
, "ParamPasswordTxt");
1347 pParamDirPathMsg
= new wxStaticText(this, PARAMETER_DIALOG_DIRPATH_MSG
, "Directory:", wxPoint( 10, 243), wxSize( -1, -1), 0, "ParamDirPathMsg");
1348 pParamDirPathTxt
= new wxTextCtrl(this, PARAMETER_DIALOG_DIRPATH_TEXT
, "", wxPoint( 10, 259), wxSize(140, 25), 0, wxDefaultValidator
, "ParamDirPathTxt");
1349 pParamSaveBtn
= new wxButton(this, PARAMETER_DIALOG_SAVE
, "&Save", wxPoint(310, 21), wxSize( 70, 35), 0, wxDefaultValidator
, "ParamSaveBtn");
1350 pParamCancelBtn
= new wxButton(this, PARAMETER_DIALOG_CANCEL
, "C&ancel", wxPoint(310, 66), wxSize( 70, 35), 0, wxDefaultValidator
, "ParamCancelBtn");
1352 // Now that all the widgets on the panel are created, its safe to allow ::OnCommand() to
1353 // handle all widget processing
1354 widgetPtrsSet
= TRUE
;
1357 savedParamSettings
= wxGetApp().params
;
1362 } // CparameterDlg constructor
1365 void CparameterDlg::OnCloseWindow(wxCloseEvent
& event
)
1367 // Put any additional checking necessary to make certain it is alright
1368 // to close the program here that is not done elsewhere
1371 bool Ok
= (wxMessageBox("No changes have been saved.\n\nAre you sure you wish exit the parameter screen?","Confirm",wxYES_NO
|wxICON_QUESTION
) == wxYES
);
1379 wxGetApp().params
= savedParamSettings
;
1382 if (GetParent() != NULL
)
1383 GetParent()->SetFocus();
1386 } // Cparameter::OnCloseWindow()
1389 void CparameterDlg::OnButton( wxCommandEvent
&event
)
1391 wxWindow
*win
= (wxWindow
*) event
.GetEventObject();
1392 OnCommand( *win
, event
);
1395 void CparameterDlg::OnCommand(wxWindow
& win
, wxCommandEvent
& event
)
1397 wxString widgetName
;
1399 widgetName
= win
.GetName();
1404 if (widgetName
== pParamSaveBtn
->GetName())
1409 tStr
= "Database parameters have been saved.";
1410 if (GetParent() != NULL
) // The parameter dialog was not called during startup due to a missing cfg file
1411 tStr
+= "\nNew parameters will take effect the next time the program is started.";
1412 wxMessageBox(tStr
,"Notice...",wxOK
| wxICON_INFORMATION
);
1419 if (widgetName
== pParamCancelBtn
->GetName())
1424 } // CparameterDlg::OnCommand()
1427 bool CparameterDlg::PutData()
1429 // Fill the data source list box
1430 FillDataSourceList();
1432 // Fill in the fields from the params object
1433 if (wxGetApp().params
.ODBCSource
&& wxStrlen(wxGetApp().params
.ODBCSource
))
1434 pParamODBCSourceList
->SetStringSelection(wxGetApp().params
.ODBCSource
);
1435 pParamUserNameTxt
->SetValue(wxGetApp().params
.UserName
);
1436 pParamPasswordTxt
->SetValue(wxGetApp().params
.Password
);
1437 pParamDirPathTxt
->SetValue(wxGetApp().params
.DirPath
);
1439 } // CparameterDlg::PutData()
1442 bool CparameterDlg::GetData()
1445 if (pParamODBCSourceList
->GetStringSelection() != "")
1447 tStr
= pParamODBCSourceList
->GetStringSelection();
1448 if (tStr
.Length() > (sizeof(wxGetApp().params
.ODBCSource
)-1))
1451 errmsg
.Printf("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());
1452 wxMessageBox(errmsg
,"Internal program error...",wxOK
| wxICON_EXCLAMATION
);
1455 strcpy(wxGetApp().params
.ODBCSource
, tStr
);
1460 tStr
= pParamUserNameTxt
->GetValue();
1461 if (tStr
.Length() > (sizeof(wxGetApp().params
.UserName
)-1))
1464 errmsg
.Printf("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());
1465 wxMessageBox(errmsg
,"Internal program error...",wxOK
| wxICON_EXCLAMATION
);
1468 strcpy(wxGetApp().params
.UserName
, tStr
);
1470 tStr
= pParamPasswordTxt
->GetValue();
1471 if (tStr
.Length() > (sizeof(wxGetApp().params
.Password
)-1))
1474 errmsg
.Printf("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());
1475 wxMessageBox(errmsg
,"Internal program error...",wxOK
| wxICON_EXCLAMATION
);
1478 strcpy(wxGetApp().params
.Password
,tStr
);
1480 tStr
= pParamDirPathTxt
->GetValue();
1481 tStr
.Replace("\\","/");
1482 if (tStr
.Length() > (sizeof(wxGetApp().params
.DirPath
)-1))
1485 errmsg
.Printf("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());
1486 wxMessageBox(errmsg
,"Internal program error...",wxOK
| wxICON_EXCLAMATION
);
1489 strcpy(wxGetApp().params
.DirPath
,tStr
);
1491 } // CparameterDlg::GetData()
1494 bool CparameterDlg::Save()
1496 Cparameters saveParams
= wxGetApp().params
;
1499 wxGetApp().params
= saveParams
;
1504 if ((paramFile
= fopen(paramFilename
, "wt")) == NULL
)
1507 tStr
.Printf("Unable to write/overwrite '%s'.",paramFilename
);
1508 wxMessageBox(tStr
,"File I/O Error...",wxOK
| wxICON_EXCLAMATION
);
1512 fputs(wxGetApp().params
.ODBCSource
, paramFile
);
1513 fputc('\n', paramFile
);
1514 fputs(wxGetApp().params
.UserName
, paramFile
);
1515 fputc('\n', paramFile
);
1516 fputs(wxGetApp().params
.Password
, paramFile
);
1517 fputc('\n', paramFile
);
1518 fputs(wxGetApp().params
.DirPath
, paramFile
);
1519 fputc('\n', paramFile
);
1523 } // CparameterDlg::Save()
1526 void CparameterDlg::FillDataSourceList()
1528 char Dsn
[SQL_MAX_DSN_LENGTH
+ 1];
1530 wxStringList strList
;
1532 while (wxDbGetDataSource(DbConnectInf
.Henv
, Dsn
, SQL_MAX_DSN_LENGTH
+1, DsDesc
, 255))
1537 char **p
= strList
.ListToArray();
1540 for (i
= 0; strlen(p
[i
]); i
++)
1541 pParamODBCSourceList
->Append(p
[i
]);
1542 } // CparameterDlg::CparameterDlg::FillDataSourceList()
1545 BEGIN_EVENT_TABLE(CqueryDlg
, wxDialog
)
1546 EVT_BUTTON(-1, CqueryDlg::OnButton
)
1547 EVT_CLOSE(CqueryDlg::OnCloseWindow
)
1550 // CqueryDlg() constructor
1551 CqueryDlg::CqueryDlg(wxWindow
*parent
, wxDB
*pDb
, char *tblName
[], char *pWhereArg
) : wxDialog (parent
, QUERY_DIALOG
, "Query", wxPoint(-1, -1), wxSize(480, 360))
1553 wxBeginBusyCursor();
1557 masterTableName
= tblName
[0];
1558 widgetPtrsSet
= FALSE
;
1561 // Initialize the WHERE clause from the string passed in
1562 pWhere
= pWhereArg
; // Save a pointer to the output buffer
1563 if (strlen(pWhere
) > DB_MAX_WHERE_CLAUSE_LEN
) // Check the length of the buffer passed in
1566 s
.Printf("Maximum where clause length exceeded.\nLength must be less than %d", DB_MAX_WHERE_CLAUSE_LEN
+1);
1567 wxMessageBox(s
,"Error...",wxOK
| wxICON_EXCLAMATION
);
1572 pQueryCol1Msg
= new wxStaticText(this, QUERY_DIALOG_COL_MSG
, "Column 1:", wxPoint( 10, 10), wxSize( 69, 16), 0, "QueryCol1Msg");
1573 pQueryCol1Choice
= new wxChoice(this, QUERY_DIALOG_COL_CHOICE
, wxPoint( 10, 27), wxSize(250, 27), 0, 0, 0, wxDefaultValidator
, "QueryCol1Choice");
1574 pQueryNotMsg
= new wxStaticText(this, QUERY_DIALOG_NOT_MSG
, "NOT", wxPoint(268, 10), wxSize( -1, -1), 0, "QueryNotMsg");
1575 pQueryNotCheck
= new wxCheckBox(this, QUERY_DIALOG_NOT_CHECKBOX
, "", wxPoint(275, 37), wxSize( 20, 20), 0, wxDefaultValidator
, "QueryNotCheck");
1577 wxString choice_strings
[9];
1578 choice_strings
[0] = "=";
1579 choice_strings
[1] = "<";
1580 choice_strings
[2] = ">";
1581 choice_strings
[3] = "<=";
1582 choice_strings
[4] = ">=";
1583 choice_strings
[5] = "Begins";
1584 choice_strings
[6] = "Contains";
1585 choice_strings
[7] = "Like";
1586 choice_strings
[8] = "Between";
1588 pQueryOperatorMsg
= new wxStaticText(this, QUERY_DIALOG_OP_MSG
, "Operator:", wxPoint(305, 10), wxSize( -1, -1), 0, "QueryOperatorMsg");
1589 pQueryOperatorChoice
= new wxChoice(this, QUERY_DIALOG_OP_CHOICE
, wxPoint(305, 27), wxSize( 80, 27), 9, choice_strings
, 0, wxDefaultValidator
, "QueryOperatorChoice");
1590 pQueryCol2Msg
= new wxStaticText(this, QUERY_DIALOG_COL2_MSG
, "Column 2:", wxPoint( 10, 65), wxSize( 69, 16), 0, "QueryCol2Msg");
1591 pQueryCol2Choice
= new wxChoice(this, QUERY_DIALOG_COL2_CHOICE
, wxPoint( 10, 82), wxSize(250, 27), 0, 0, 0, wxDefaultValidator
, "QueryCol2Choice");
1592 pQuerySqlWhereMsg
= new wxStaticText(this, QUERY_DIALOG_WHERE_MSG
, "SQL where clause:", wxPoint( 10, 141), wxSize( -1, -1), 0, "QuerySqlWhereMsg");
1593 pQuerySqlWhereMtxt
= new wxTextCtrl(this, QUERY_DIALOG_WHERE_TEXT
, "", wxPoint( 10, 159), wxSize(377, 134), wxTE_MULTILINE
, wxDefaultValidator
, "QuerySqlWhereMtxt");
1594 pQueryAddBtn
= new wxButton(this, QUERY_DIALOG_ADD
, "&Add", wxPoint(406, 24), wxSize( 56, 26), 0, wxDefaultValidator
, "QueryAddBtn");
1595 pQueryAndBtn
= new wxButton(this, QUERY_DIALOG_AND
, "A&nd", wxPoint(406, 58), wxSize( 56, 26), 0, wxDefaultValidator
, "QueryAndBtn");
1596 pQueryOrBtn
= new wxButton(this, QUERY_DIALOG_OR
, "&Or", wxPoint(406, 92), wxSize( 56, 26), 0, wxDefaultValidator
, "QueryOrBtn");
1597 pQueryLParenBtn
= new wxButton(this, QUERY_DIALOG_LPAREN
, "(", wxPoint(406, 126), wxSize( 26, 26), 0, wxDefaultValidator
, "QueryLParenBtn");
1598 pQueryRParenBtn
= new wxButton(this, QUERY_DIALOG_RPAREN
, ")", wxPoint(436, 126), wxSize( 26, 26), 0, wxDefaultValidator
, "QueryRParenBtn");
1599 pQueryDoneBtn
= new wxButton(this, QUERY_DIALOG_DONE
, "&Done", wxPoint(406, 185), wxSize( 56, 26), 0, wxDefaultValidator
, "QueryDoneBtn");
1600 pQueryClearBtn
= new wxButton(this, QUERY_DIALOG_CLEAR
, "C&lear", wxPoint(406, 218), wxSize( 56, 26), 0, wxDefaultValidator
, "QueryClearBtn");
1601 pQueryCountBtn
= new wxButton(this, QUERY_DIALOG_COUNT
, "&Count", wxPoint(406, 252), wxSize( 56, 26), 0, wxDefaultValidator
, "QueryCountBtn");
1602 pQueryValue1Msg
= new wxStaticText(this, QUERY_DIALOG_VALUE1_MSG
, "Value:", wxPoint(277, 66), wxSize( -1, -1), 0, "QueryValue1Msg");
1603 pQueryValue1Txt
= new wxTextCtrl(this, QUERY_DIALOG_VALUE1_TEXT
, "", wxPoint(277, 83), wxSize(108, 25), 0, wxDefaultValidator
, "QueryValue1Txt");
1604 pQueryValue2Msg
= new wxStaticText(this, QUERY_DIALOG_VALUE2_MSG
, "AND", wxPoint(238, 126), wxSize( -1, -1), 0, "QueryValue2Msg");
1605 pQueryValue2Txt
= new wxTextCtrl(this, QUERY_DIALOG_VALUE2_TEXT
, "", wxPoint(277, 120), wxSize(108, 25), 0, wxDefaultValidator
, "QueryValue2Txt");
1606 pQueryHintGrp
= new wxStaticBox(this, QUERY_DIALOG_HINT_GROUP
, "", wxPoint( 10, 291), wxSize(377, 40), 0, "QueryHintGrp");
1607 pQueryHintMsg
= new wxStaticText(this, QUERY_DIALOG_HINT_MSG
, "", wxPoint( 16, 306), wxSize( -1, -1), 0, "QueryHintMsg");
1609 widgetPtrsSet
= TRUE
;
1610 // Initialize the dialog
1612 pQueryCol2Choice
->Append("VALUE -->");
1613 colInf
= pDB
->GetColumns(tblName
);
1619 tStr
= "ODBC error during GetColumns()\n\n";
1620 tStr
+= GetExtendedDBErrorMsg(__FILE__
,__LINE__
);
1621 wxMessageBox(tStr
,"ODBC Error...",wxOK
| wxICON_EXCLAMATION
);
1626 for (i
= 0; colInf
[i
].colName
&& strlen(colInf
[i
].colName
); i
++)
1628 // If there is more than one table being queried, qualify
1629 // the column names with the table name prefix.
1630 if (tblName
[1] && strlen(tblName
[1]))
1632 qualName
.Printf("%s.%s", colInf
[i
].tableName
, colInf
[i
].colName
);
1633 pQueryCol1Choice
->Append(qualName
);
1634 pQueryCol2Choice
->Append(qualName
);
1636 else // Single table query, append just the column names
1638 pQueryCol1Choice
->Append(colInf
[i
].colName
);
1639 pQueryCol2Choice
->Append(colInf
[i
].colName
);
1643 pQueryCol1Choice
->SetSelection(0);
1644 pQueryCol2Choice
->SetSelection(0);
1645 pQueryOperatorChoice
->SetSelection(0);
1647 pQueryValue2Msg
->Show(FALSE
);
1648 pQueryValue2Txt
->Show(FALSE
);
1650 pQueryHintMsg
->SetLabel(langQRY_EQ
);
1652 pQuerySqlWhereMtxt
->SetValue(pWhere
);
1656 // Display the dialog window
1660 } // CqueryDlg() constructor
1663 CqueryDlg::~CqueryDlg()
1665 } // CqueryDlg::~CqueryDlg() destructor
1668 void CqueryDlg::OnButton( wxCommandEvent
&event
)
1670 wxWindow
*win
= (wxWindow
*) event
.GetEventObject();
1671 OnCommand( *win
, event
);
1674 void CqueryDlg::OnCommand(wxWindow
& win
, wxCommandEvent
& event
)
1676 // Widget pointers won't be set when the dialog is constructed.
1677 // Control is passed through this function once for each widget on
1678 // a dialog as the dialog is constructed.
1682 wxString widgetName
= win
.GetName();
1684 // Operator choice box
1685 if (widgetName
== pQueryOperatorChoice
->GetName())
1687 // Set the help text
1688 switch((qryOp
) pQueryOperatorChoice
->GetSelection())
1691 pQueryHintMsg
->SetLabel(langQRY_EQ
);
1694 pQueryHintMsg
->SetLabel(langQRY_LT
);
1697 pQueryHintMsg
->SetLabel(langQRY_GT
);
1700 pQueryHintMsg
->SetLabel(langQRY_LE
);
1703 pQueryHintMsg
->SetLabel(langQRY_GE
);
1706 pQueryHintMsg
->SetLabel(langQRY_BEGINS
);
1709 pQueryHintMsg
->SetLabel(langQRY_CONTAINS
);
1712 pQueryHintMsg
->SetLabel(langQRY_LIKE
);
1715 pQueryHintMsg
->SetLabel(langQRY_BETWEEN
);
1719 // Hide the value2 widget
1720 pQueryValue2Msg
->Show(FALSE
); // BETWEEN will show this widget
1721 pQueryValue2Txt
->Show(FALSE
); // BETWEEN will show this widget
1723 // Disable the NOT operator for <, <=, >, >=
1724 switch((qryOp
) pQueryOperatorChoice
->GetSelection())
1730 pQueryNotCheck
->SetValue(0);
1731 pQueryNotCheck
->Enable(FALSE
);
1734 pQueryNotCheck
->Enable(TRUE
);
1738 // Manipulate the dialog to handle the selected operator
1739 switch((qryOp
) pQueryOperatorChoice
->GetSelection())
1746 pQueryCol2Choice
->Enable(TRUE
);
1747 if (pQueryCol2Choice
->GetSelection()) // Column name is highlighted
1749 pQueryValue1Msg
->Show(FALSE
);
1750 pQueryValue1Txt
->Show(FALSE
);
1752 else // "Value" is highlighted
1754 pQueryValue1Msg
->Show(TRUE
);
1755 pQueryValue1Txt
->Show(TRUE
);
1756 pQueryValue1Txt
->SetFocus();
1762 pQueryCol2Choice
->SetSelection(0);
1763 pQueryCol2Choice
->Enable(FALSE
);
1764 pQueryValue1Msg
->Show(TRUE
);
1765 pQueryValue1Txt
->Show(TRUE
);
1766 pQueryValue1Txt
->SetFocus();
1769 pQueryCol2Choice
->SetSelection(0);
1770 pQueryCol2Choice
->Enable(FALSE
);
1771 pQueryValue2Msg
->Show(TRUE
);
1772 pQueryValue2Txt
->Show(TRUE
);
1773 pQueryValue1Msg
->Show(TRUE
);
1774 pQueryValue1Txt
->Show(TRUE
);
1775 pQueryValue1Txt
->SetFocus();
1781 } // Operator choice box
1784 if (widgetName
== pQueryCol2Choice
->GetName())
1786 if (pQueryCol2Choice
->GetSelection()) // Column name is highlighted
1788 pQueryValue1Msg
->Show(FALSE
);
1789 pQueryValue1Txt
->Show(FALSE
);
1791 else // "Value" is highlighted
1793 pQueryValue1Msg
->Show(TRUE
);
1794 pQueryValue1Txt
->Show(TRUE
);
1795 pQueryValue1Txt
->SetFocus();
1799 } // Column 2 choice
1802 if (widgetName
== pQueryAddBtn
->GetName())
1810 if (widgetName
== pQueryAndBtn
->GetName())
1812 AppendToWhere(" AND\n");
1818 if (widgetName
== pQueryOrBtn
->GetName())
1820 AppendToWhere(" OR\n");
1825 // Left Paren button
1826 if (widgetName
== pQueryLParenBtn
->GetName())
1831 } // Left Paren button
1833 // Right paren button
1834 if (widgetName
== pQueryRParenBtn
->GetName())
1839 } // Right Paren button
1842 if (widgetName
== pQueryDoneBtn
->GetName())
1844 // Be sure the where clause will not overflow the output buffer
1845 if (strlen(pQuerySqlWhereMtxt
->GetValue()) > DB_MAX_WHERE_CLAUSE_LEN
)
1848 s
.Printf("Maximum where clause length exceeded.\nLength must be less than %d", DB_MAX_WHERE_CLAUSE_LEN
+1);
1849 wxMessageBox(s
,"Error...",wxOK
| wxICON_EXCLAMATION
);
1852 // Validate the where clause for things such as matching parens
1853 if (!ValidateWhereClause())
1855 // Copy the where clause to the output buffer and exit
1856 strcpy(pWhere
, pQuerySqlWhereMtxt
->GetValue());
1863 if (widgetName
== pQueryClearBtn
->GetName())
1865 bool Ok
= (wxMessageBox("Are you sure you wish to clear the Query?","Confirm",wxYES_NO
|wxICON_QUESTION
) == wxYES
);
1868 pQuerySqlWhereMtxt
->SetValue("");
1874 if (widgetName
== pQueryCountBtn
->GetName())
1876 wxBeginBusyCursor();
1883 } // CqueryDlg::OnCommand
1886 void CqueryDlg::OnCloseWindow(wxCloseEvent
& event
)
1901 GetParent()->SetFocus();
1908 } // CqueryDlg::OnCloseWindow()
1911 void CqueryDlg::AppendToWhere(char *s
)
1913 wxString whereStr
= pQuerySqlWhereMtxt
->GetValue();
1915 pQuerySqlWhereMtxt
->SetValue(whereStr
);
1917 } // CqueryDlg::AppendToWhere()
1920 void CqueryDlg::ProcessAddBtn()
1922 qryOp oper
= (qryOp
) pQueryOperatorChoice
->GetSelection();
1924 // Verify that eveything is filled in correctly
1925 if (pQueryCol2Choice
->GetSelection() == 0) // "Value" is selected
1927 // Verify that value 1 is filled in
1928 if (strlen(pQueryValue1Txt
->GetValue()) == 0)
1931 pQueryValue1Txt
->SetFocus();
1934 // For the BETWEEN operator, value 2 must be filled in as well
1935 if (oper
== qryOpBETWEEN
&&
1936 strlen(pQueryValue2Txt
->GetValue()) == 0)
1939 pQueryValue2Txt
->SetFocus();
1944 // Build the expression and append it to the where clause window
1945 wxString s
= pQueryCol1Choice
->GetStringSelection();
1947 if (pQueryNotCheck
->GetValue() && (oper
!= qryOpEQ
))
1953 if (pQueryNotCheck
->GetValue()) // NOT box is checked
1982 int col1Idx
= pQueryCol1Choice
->GetSelection();
1985 if (colInf
[col1Idx
].sqlDataType
== SQL_VARCHAR
||
1986 oper
== qryOpBEGINS
||
1987 oper
== qryOpCONTAINS
||
1991 if (pQueryCol2Choice
->GetSelection()) // Column name
1992 s
+= pQueryCol2Choice
->GetStringSelection();
1993 else // Column 2 is a "value"
1997 if (oper
== qryOpCONTAINS
)
1999 s
+= pQueryValue1Txt
->GetValue();
2000 if (oper
== qryOpCONTAINS
|| oper
== qryOpBEGINS
)
2006 if (oper
== qryOpBETWEEN
)
2011 s
+= pQueryValue2Txt
->GetValue();
2016 AppendToWhere((char*) (const char*) s
);
2018 } // CqueryDlg::ProcessAddBtn()
2021 void CqueryDlg::ProcessCountBtn()
2023 if (!ValidateWhereClause())
2026 if (dbTable
== 0) // wxTable object needs to be created and opened
2028 if (!(dbTable
= new wxTable(pDB
, masterTableName
, 0, NULL
, !QUERY_ONLY
, DbConnectInf
.defaultDir
)))
2030 wxMessageBox("Memory allocation failed creating a wxTable object.","Error...",wxOK
| wxICON_EXCLAMATION
);
2033 if (!dbTable
->Open())
2036 tStr
= "ODBC error during Open()\n\n";
2037 tStr
+= GetExtendedDBErrorMsg(__FILE__
,__LINE__
);
2038 wxMessageBox(tStr
,"ODBC Error...",wxOK
| wxICON_EXCLAMATION
);
2043 // Count() with WHERE clause
2046 whereStr
= pQuerySqlWhereMtxt
->GetValue();
2047 dbTable
->where
= (char *)whereStr
.GetData();
2048 ULONG whereCnt
= dbTable
->Count();
2050 // Count() of all records in the table
2052 ULONG totalCnt
= dbTable
->Count();
2054 if (whereCnt
> 0 || totalCnt
== 0)
2057 tStr
.Printf("%lu of %lu records match the query criteria.",whereCnt
,totalCnt
);
2058 wxMessageBox(tStr
,"Notice...",wxOK
| wxICON_INFORMATION
);
2063 tStr
.Printf("%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
);
2064 wxMessageBox(tStr
,"Notice...",wxOK
| wxICON_INFORMATION
);
2067 // After a wxMessageBox, the focus does not necessarily return to the
2068 // window which was the focus when the message box popped up, so return
2069 // focus to the Query dialog for certain
2072 } // CqueryDlg::ProcessCountBtn()
2075 bool CqueryDlg::ValidateWhereClause()
2077 wxString where
= pQuerySqlWhereMtxt
->GetValue();
2079 if (where
.Freq('(') != where
.Freq(')'))
2081 wxMessageBox("There are mismatched parenthesis in the constructed where clause","Error...",wxOK
| wxICON_EXCLAMATION
);
2084 // After a wxMessageBox, the focus does not necessarily return to the
2085 // window which was the focus when the message box popped up, so return
2086 // focus to the Query dialog for certain
2091 } // CqueryDlg::ValidateWhereClause()
2097 TEST CODE FOR TESTING THE wxDbCreateDataSource() FUNCTION
2100 result = wxDbCreateDataSource("Microsoft Access Driver (*.mdb)","GLT-TEST2","GLT-Descrip",FALSE,"",this);
2103 // check for errors caused by ConfigDSN based functions
2106 wxChar errMsg[500+1];
2109 SQLInstallerError(1,&retcode,errMsg,500,&cb);
2111 wxMessageBox("FAILED creating data source","FAILED");
2114 wxMessageBox("SUCCEEDED creating data source","SUCCESS");