]> git.saurik.com Git - wxWidgets.git/commitdiff
Massive cleanup of the code.
authorGeorge Tasker <gtasker@allenbrook.com>
Sat, 3 Feb 2001 17:52:58 +0000 (17:52 +0000)
committerGeorge Tasker <gtasker@allenbrook.com>
Sat, 3 Feb 2001 17:52:58 +0000 (17:52 +0000)
More Unicode support added (though untested).
Added TONS of comments
Changed code to demonstrate the new wxDbConnectInf class
ODBC environment handle now managed via the wxDbConnectInf class
Fixed bug where editing a displayed record would not save if the user name was changed.
Other minor bug fixes

git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@9276 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775

samples/db/dbtest.cpp
samples/db/dbtest.h
samples/db/listdb.cpp
samples/db/listdb.h

index 5f217eaeb69bafccbe6928f3c8341d5724a4777b..9a28a5ddadb13bfc541bdf16d8d8a17cd9f47f11 100644 (file)
@@ -51,33 +51,8 @@ extern wxDbList WXDLLEXPORT *PtrBegDbList;    /* from db.cpp, used in getting ba
 
 IMPLEMENT_APP(DatabaseDemoApp)
 
 
 IMPLEMENT_APP(DatabaseDemoApp)
 
-extern wxChar ListDB_Selection[];        /* Used to return the first column value for the selected line from the listDB routines */
-extern wxChar ListDB_Selection2[];    /* Used to return the second column value for the selected line from the listDB routines */
-
-DatabaseDemoFrame *DemoFrame;       /* Pointer to the main frame */
-
-/* Pointer to the main database connection used in the program.  This
- * pointer would normally be used for doing things as database lookups
- * for user login names and passwords, getting workstation settings, etc.
- * ---> IMPORTANT <---
- * 
- *        For each database object created which uses this wxDb pointer
- *    connection to the database, when a CommitTrans() or RollBackTrans()
- *    will commit or rollback EVERY object which uses this wxDb pointer.
- *
- *    To allow each table object (those derived from wxDbTable) to be 
- *    individually committed or rolled back, you MUST use a different
- *    instance of wxDb in the constructor of the table.  Doing so creates 
- *        more overhead, and will use more database connections (some DBs have
- *    connection limits...), so use connections sparringly.
- *
- *        It is recommended that one "main" database connection be created for
- *        the entire program to use for READ-ONLY database accesses, but for each
- *        table object which will do a CommitTrans() or RollbackTrans() that a
- *        new wxDb object be created and used for it.
- */
-wxDb    *READONLY_DB;
+extern wxChar ListDB_Selection[];   /* Used to return the first column value for the selected line from the listDB routines */
+extern wxChar ListDB_Selection2[];  /* Used to return the second column value for the selected line from the listDB routines */
 
 const char *GetExtendedDBErrorMsg(wxDb *pDb, char *ErrFile, int ErrLine)
 {
 
 const char *GetExtendedDBErrorMsg(wxDb *pDb, char *ErrFile, int ErrLine)
 {
@@ -121,6 +96,8 @@ const char *GetExtendedDBErrorMsg(wxDb *pDb, char *ErrFile, int ErrLine)
 
 bool DatabaseDemoApp::OnInit()
 {
 
 bool DatabaseDemoApp::OnInit()
 {
+    DbConnectInf = NULL;
+
     // Create the main frame window
     DemoFrame = new DatabaseDemoFrame(NULL, wxT("wxWindows Database Demo"), wxPoint(50, 50), wxSize(537, 480));
 
     // Create the main frame window
     DemoFrame = new DatabaseDemoFrame(NULL, wxT("wxWindows Database Demo"), wxPoint(50, 50), wxSize(537, 480));
 
@@ -146,13 +123,6 @@ bool DatabaseDemoApp::OnInit()
     menu_bar->Append(about_menu, wxT("&About"));
     DemoFrame->SetMenuBar(menu_bar);
 
     menu_bar->Append(about_menu, wxT("&About"));
     DemoFrame->SetMenuBar(menu_bar);
 
-    // Initialize the ODBC Environment for Database Operations
-    if (SQLAllocEnv(&DbConnectInf.Henv) != SQL_SUCCESS)
-    {
-        wxMessageBox(wxT("A problem occured while trying to get a connection to the data source"),wxT("DB CONNECTION ERROR"),wxOK | wxICON_EXCLAMATION);
-        return NULL;
-    }
-
     params.ODBCSource[0] = 0;
     params.UserName[0]   = 0;
     params.Password[0]   = 0;
     params.ODBCSource[0] = 0;
     params.UserName[0]   = 0;
     params.Password[0]   = 0;
@@ -161,15 +131,57 @@ bool DatabaseDemoApp::OnInit()
     // Show the frame
     DemoFrame->Show(TRUE);
 
     // Show the frame
     DemoFrame->Show(TRUE);
 
+    ReadParamFile(params);
+
+    // Passing NULL for the SQL environment handle causes
+    // the wxDbConnectInf constructor to obtain a handle
+    // for you.
+    //
+    // WARNING: Be certain that you do not free this handle
+    //          directly with SQLFreeEnv().  Use either the
+    //          method ::FreeHenv() or delete the DbConnectInf.
+    DbConnectInf = new wxDbConnectInf(NULL, params.ODBCSource, params.UserName, 
+                                      params.Password, params.DirPath);
+
+    if (!DbConnectInf || !DbConnectInf->GetHenv())
+    {
+        wxMessageBox(wxT("Unable to define data source connection info."), wxT("DB CONNECTION ERROR..."),wxOK | wxICON_EXCLAMATION);
+        delete DbConnectInf;
+    }
+
+
+    READONLY_DB = wxDbGetConnection(DbConnectInf);
+    if (READONLY_DB == 0)
+    {
+        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);
+        DemoFrame->BuildParameterDialog(NULL);
+        DbConnectInf->SetDsn("");
+        DbConnectInf->SetUid("");
+        DbConnectInf->SetPassword("");
+        wxMessageBox(wxT("Now exiting program.\n\nRestart program to try any new settings."),wxT("Notice..."),wxOK | wxICON_INFORMATION);
+        return(FALSE);
+    }
+
+    DemoFrame->BuildEditorDialog();
+
+    // Show the frame
+    DemoFrame->Refresh();
+
+    return TRUE;
+}  // DatabaseDemoApp::OnInit()
+
+
+bool DatabaseDemoApp::ReadParamFile(Cparameters &params)
+{
     FILE *paramFile;
     FILE *paramFile;
-    if ((paramFile = fopen(paramFilename, wxT("r"))) == NULL)
+    if ((paramFile = fopen(PARAM_FILENAME, wxT("r"))) == NULL)
     {
         wxString tStr;
     {
         wxString tStr;
-        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."),paramFilename);
+        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);
         wxMessageBox(tStr,wxT("File I/O Error..."),wxOK | wxICON_EXCLAMATION);
 
         DemoFrame->BuildParameterDialog(NULL);
         wxMessageBox(tStr,wxT("File I/O Error..."),wxOK | wxICON_EXCLAMATION);
 
         DemoFrame->BuildParameterDialog(NULL);
-        if ((paramFile = fopen(paramFilename, wxT("r"))) == NULL)
+        if ((paramFile = fopen(PARAM_FILENAME, wxT("r"))) == NULL)
             return FALSE;
     }
 
             return FALSE;
     }
 
@@ -192,31 +204,89 @@ bool DatabaseDemoApp::OnInit()
 
     fclose(paramFile);
 
 
     fclose(paramFile);
 
-    // Connect to datasource
-    DbConnectInf.Dsn        = params.ODBCSource;    // ODBC data source name (created with ODBC Administrator under Win95/NT)
-    DbConnectInf.Uid        = params.UserName;      // database username - must already exist in the data source
-    DbConnectInf.AuthStr    = params.Password;      // password database username
-    DbConnectInf.defaultDir = params.DirPath;       // path where the table exists (needed for dBase)
+    return TRUE;
+}  // DatabaseDemoApp::ReadParamFile()
 
 
-    READONLY_DB = wxDbGetConnection(&DbConnectInf);
-    if (READONLY_DB == 0)
+
+bool DatabaseDemoApp::WriteParamFile(Cparameters &params)
+{
+    FILE *paramFile;
+    if ((paramFile = fopen(PARAM_FILENAME, wxT("wt"))) == NULL)
     {
     {
-        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);
-        DemoFrame->BuildParameterDialog(NULL);
-        DbConnectInf.Dsn.Empty();
-        DbConnectInf.Uid.Empty();
-        DbConnectInf.AuthStr.Empty();
-        wxMessageBox(wxT("Now exiting program.\n\nRestart program to try any new settings."),wxT("Notice..."),wxOK | wxICON_INFORMATION);
-        return(FALSE);
+        wxString tStr;
+        tStr.Printf(wxT("Unable to write/overwrite '%s'."),PARAM_FILENAME);
+        wxMessageBox(tStr,wxT("File I/O Error..."),wxOK | wxICON_EXCLAMATION);
+        return FALSE;
     }
 
     }
 
-    DemoFrame->BuildEditorDialog();
-
-    // Show the frame
-    DemoFrame->Refresh();
+    fputs(wxGetApp().params.ODBCSource, paramFile);
+    fputc(wxT('\n'), paramFile);
+    fputs(wxGetApp().params.UserName, paramFile);
+    fputc(wxT('\n'), paramFile);
+    fputs(wxGetApp().params.Password, paramFile);
+    fputc(wxT('\n'), paramFile);
+    fputs(wxGetApp().params.DirPath, paramFile);
+    fputc(wxT('\n'), paramFile);
+    fclose(paramFile);
 
     return TRUE;
 
     return TRUE;
-}  // DatabaseDemoApp::OnInit()
+}  // DatabaseDemoApp::WriteParamFile()
+
+
+void DatabaseDemoApp::CreateDataTable(bool recreate)
+{
+    bool Ok = TRUE;
+    if (recreate)
+       Ok = (wxMessageBox(wxT("Any data currently residing in the table will be erased.\n\nAre you sure?"),wxT("Confirm"),wxYES_NO|wxICON_QUESTION) == wxYES);
+
+    if (!Ok)
+        return;
+
+    wxBeginBusyCursor();
+
+    bool success = TRUE;
+
+    // Use a temporary instance of a new Ccontact table object
+    // for creating the table within the datasource.
+    Ccontact *Contact = new Ccontact();
+
+    if (!Contact)
+    {
+        wxEndBusyCursor();
+        wxMessageBox(wxT("Error allocating memory for 'Ccontact'object.\n\nTable was not created."),wxT("Error..."),wxOK | wxICON_EXCLAMATION);
+        return;
+    }
+
+    if (!Contact->CreateTable(recreate))
+    {
+        wxEndBusyCursor();
+        wxString tStr;
+        tStr  = wxT("Error creating CONTACTS table.\nTable was not created.\n\n");
+        tStr += GetExtendedDBErrorMsg(Contact->GetDb(),__FILE__,__LINE__);
+        wxMessageBox(tStr,wxT("ODBC Error..."),wxOK | wxICON_EXCLAMATION);
+        success = FALSE;
+    }
+    else
+    {
+        if (!Contact->CreateIndexes())
+        {
+            wxEndBusyCursor();
+            wxString tStr;
+            tStr  = wxT("Error creating CONTACTS indexes.\nIndexes will be unavailable.\n\n");
+            tStr += GetExtendedDBErrorMsg(Contact->GetDb(),__FILE__,__LINE__);
+            wxMessageBox(tStr,wxT("ODBC Error..."),wxOK | wxICON_EXCLAMATION);
+            success = FALSE;
+        }
+    }
+    while (wxIsBusy())
+        wxEndBusyCursor();
+
+    delete Contact;
+    Contact = NULL;
+
+    if (success)
+        wxMessageBox(wxT("Table and index(es) were successfully created."),wxT("Notice..."),wxOK | wxICON_INFORMATION);
+}  // DatabaseDemoApp::CreateDataTable()
 
 
 BEGIN_EVENT_TABLE(DatabaseDemoFrame, wxFrame)
 
 
 BEGIN_EVENT_TABLE(DatabaseDemoFrame, wxFrame)
@@ -243,13 +313,13 @@ DatabaseDemoFrame::DatabaseDemoFrame(wxFrame *frame, const wxString& title,
 
 void DatabaseDemoFrame::OnCreate(wxCommandEvent& event)
 {
 
 void DatabaseDemoFrame::OnCreate(wxCommandEvent& event)
 {
-    CreateDataTable(FALSE);
+    wxGetApp().CreateDataTable(FALSE);
 }  // DatabaseDemoFrame::OnCreate()
 
 
 void DatabaseDemoFrame::OnRecreateTable(wxCommandEvent& event)
 {
 }  // DatabaseDemoFrame::OnCreate()
 
 
 void DatabaseDemoFrame::OnRecreateTable(wxCommandEvent& event)
 {
-    CreateDataTable(TRUE);
+    wxGetApp().CreateDataTable(TRUE);
 }  // DatabaseDemoFrame::OnRecreate()
 
 
 }  // DatabaseDemoFrame::OnRecreate()
 
 
@@ -300,11 +370,10 @@ void DatabaseDemoFrame::OnAbout(wxCommandEvent& event)
 }  // DatabaseDemoFrame::OnAbout()
 
 
 }  // DatabaseDemoFrame::OnAbout()
 
 
+// Put any additional checking necessary to make certain it is alright
+// to close the program here that is not done elsewhere
 void DatabaseDemoFrame::OnCloseWindow(wxCloseEvent& event)
 {
 void DatabaseDemoFrame::OnCloseWindow(wxCloseEvent& event)
 {
-    // Put any additional checking necessary to make certain it is alright
-    // to close the program here that is not done elsewhere
-
     // Clean up time
     if (pEditorDlg && pEditorDlg->Close())
         pEditorDlg = NULL;
     // Clean up time
     if (pEditorDlg && pEditorDlg->Close())
         pEditorDlg = NULL;
@@ -321,67 +390,17 @@ void DatabaseDemoFrame::OnCloseWindow(wxCloseEvent& event)
     // previously cached.
     wxDbCloseConnections();
 
     // previously cached.
     wxDbCloseConnections();
 
-    // Cleans up the environment space allocated for the SQL/ODBC connection handle
-    SQLFreeEnv(DbConnectInf.Henv);
+    // Deletion of the wxDbConnectInf instance must be the LAST thing done that
+    // has anything to do with the database.  Deleting this before disconnecting,
+    // freeing/closing connections, etc will result in a crash!
+    delete wxGetApp().DbConnectInf;
+    wxGetApp().DbConnectInf = NULL;
 
     this->Destroy();
 
 }  // DatabaseDemoFrame::OnCloseWindow()
 
 
 
     this->Destroy();
 
 }  // DatabaseDemoFrame::OnCloseWindow()
 
 
-void DatabaseDemoFrame::CreateDataTable(bool recreate)
-{
-    bool Ok = TRUE;
-    if (recreate)
-       Ok = (wxMessageBox(wxT("Any data currently residing in the table will be erased.\n\nAre you sure?"),wxT("Confirm"),wxYES_NO|wxICON_QUESTION) == wxYES);
-
-    if (!Ok)
-        return;
-
-    wxBeginBusyCursor();
-
-    bool success = TRUE;
-
-    Ccontact *Contact = new Ccontact();
-    if (!Contact)
-    {
-        wxEndBusyCursor();
-        wxMessageBox(wxT("Error allocating memory for 'Ccontact'object.\n\nTable was not created."),wxT("Error..."),wxOK | wxICON_EXCLAMATION);
-        return;
-    }
-
-    if (!Contact->CreateTable(recreate))
-    {
-        wxEndBusyCursor();
-        wxString tStr;
-        tStr  = wxT("Error creating CONTACTS table.\nTable was not created.\n\n");
-        tStr += GetExtendedDBErrorMsg(Contact->GetDb(),__FILE__,__LINE__);
-        wxMessageBox(tStr,wxT("ODBC Error..."),wxOK | wxICON_EXCLAMATION);
-        success = FALSE;
-    }
-    else
-    {
-        if (!Contact->CreateIndexes())
-        {
-            wxEndBusyCursor();
-            wxString tStr;
-            tStr  = wxT("Error creating CONTACTS indexes.\nIndexes will be unavailable.\n\n");
-            tStr += GetExtendedDBErrorMsg(Contact->GetDb(),__FILE__,__LINE__);
-            wxMessageBox(tStr,wxT("ODBC Error..."),wxOK | wxICON_EXCLAMATION);
-            success = FALSE;
-        }
-    }
-    while (wxIsBusy())
-        wxEndBusyCursor();
-
-    delete Contact;
-    Contact = NULL;
-
-    if (success)
-        wxMessageBox(wxT("Table and index(es) were successfully created."),wxT("Notice..."),wxOK | wxICON_INFORMATION);
-}  // DatabaseDemoFrame::CreateDataTable()
-
-
 void DatabaseDemoFrame::BuildEditorDialog()
 {
     pEditorDlg = NULL;
 void DatabaseDemoFrame::BuildEditorDialog()
 {
     pEditorDlg = NULL;
@@ -394,13 +413,13 @@ void DatabaseDemoFrame::BuildEditorDialog()
             pEditorDlg->Close();
             pEditorDlg = NULL;
             wxMessageBox(wxT("Unable to initialize the editor dialog for some reason"),wxT("Error..."),wxOK | wxICON_EXCLAMATION);
             pEditorDlg->Close();
             pEditorDlg = NULL;
             wxMessageBox(wxT("Unable to initialize the editor dialog for some reason"),wxT("Error..."),wxOK | wxICON_EXCLAMATION);
-            DemoFrame->Close();
+            Close();
         }
     } 
     else
     {
         wxMessageBox(wxT("Unable to create the editor dialog for some reason"),wxT("Error..."),wxOK | wxICON_EXCLAMATION);
         }
     } 
     else
     {
         wxMessageBox(wxT("Unable to create the editor dialog for some reason"),wxT("Error..."),wxOK | wxICON_EXCLAMATION);
-        DemoFrame->Close();
+        Close();
     }
 }  // DatabaseDemoFrame::BuildEditorDialog()
 
     }
 }  // DatabaseDemoFrame::BuildEditorDialog()
 
@@ -426,7 +445,9 @@ void DatabaseDemoFrame::BuildParameterDialog(wxWindow *parent)
  *     or creating a table objects which use the same pDb, know that all the objects
  *     will be committed or rolled back when any of the objects has this function call made.
  */
  *     or creating a table objects which use the same pDb, know that all the objects
  *     will be committed or rolled back when any of the objects has this function call made.
  */
-Ccontact::Ccontact (wxDb *pwxDb) : wxDbTable(pwxDb ? pwxDb : wxDbGetConnection(&DbConnectInf), CONTACT_TABLE_NAME,CONTACT_NO_COLS, wxT(""), !wxDB_QUERY_ONLY, DbConnectInf.defaultDir)
+Ccontact::Ccontact (wxDb *pwxDb) : wxDbTable(pwxDb ? pwxDb : wxDbGetConnection(wxGetApp().DbConnectInf),
+                                             CONTACT_TABLE_NAME, CONTACT_NO_COLS, wxT(""),
+                                             !wxDB_QUERY_ONLY, wxGetApp().DbConnectInf->GetDefaultDir())
 {
     // This is used to represent whether the database connection should be released
     // when this instance of the object is deleted.  If using the same connection
 {
     // This is used to represent whether the database connection should be released
     // when this instance of the object is deleted.  If using the same connection
@@ -529,7 +550,7 @@ bool Ccontact::CreateIndexes(void)
  * very efficient and tighter coding so that it is available where ever the object
  * is.  Great for use with multiple tables when not using views or outer joins
  */
  * very efficient and tighter coding so that it is available where ever the object
  * is.  Great for use with multiple tables when not using views or outer joins
  */
-bool Ccontact::FetchByName(wxChar *name)
+bool Ccontact::FetchByName(const wxString &name)
 {
     whereStr.Printf(wxT("NAME = '%s'"),name);
     SetWhereClause(whereStr.c_str());
 {
     whereStr.Printf(wxT("NAME = '%s'"),name);
     SetWhereClause(whereStr.c_str());
@@ -705,7 +726,7 @@ void CeditorDlg::OnCommand(wxWindow& win, wxCommandEvent& event)
         else
         {
             // Requery previous record
         else
         {
             // Requery previous record
-            if (Contact->FetchByName((wxChar*) (const wxChar*) saveName))
+            if (Contact->FetchByName(saveName))
             {
                 PutData();
                 SetMode(mView);
             {
                 PutData();
                 SetMode(mView);
@@ -821,9 +842,9 @@ void CeditorDlg::OnCommand(wxWindow& win, wxCommandEvent& event)
 
         if (Contact->GetDb()->Dbms() != dbmsPOSTGRES && Contact->GetDb()->Dbms() != dbmsMY_SQL)
         {
 
         if (Contact->GetDb()->Dbms() != dbmsPOSTGRES && Contact->GetDb()->Dbms() != dbmsMY_SQL)
         {
-            Contact->whereStr        = wxT("NAME = (SELECT MIN(NAME) FROM ");
-            Contact->whereStr        += CONTACT_TABLE_NAME;
-            Contact->whereStr        += wxT(")");
+            Contact->whereStr  = wxT("NAME = (SELECT MIN(NAME) FROM ");
+            Contact->whereStr += CONTACT_TABLE_NAME;
+            Contact->whereStr += wxT(")");
         }
 
         Contact->SetWhereClause(Contact->whereStr.c_str());
         }
 
         Contact->SetWhereClause(Contact->whereStr.c_str());
@@ -846,21 +867,23 @@ void CeditorDlg::OnCommand(wxWindow& win, wxCommandEvent& event)
 
     if (widgetName == pNameListBtn->GetName())
     {
 
     if (widgetName == pNameListBtn->GetName())
     {
-        new ClookUpDlg(/* wxWindow  *parent        */ this,
+        new ClookUpDlg(/* wxWindow    *parent        */ this,
                        /* wxChar      *windowTitle   */ wxT("Select contact name"),
                        /* wxChar      *tableName     */ (wxChar *) CONTACT_TABLE_NAME,
                        /* wxChar      *dispCol1      */ wxT("NAME"),
                        /* wxChar      *dispCol2      */ wxT("JOINDATE"),
                        /* wxChar      *where         */ wxT(""),
                        /* wxChar      *orderBy       */ wxT("NAME"),
                        /* wxChar      *windowTitle   */ wxT("Select contact name"),
                        /* wxChar      *tableName     */ (wxChar *) CONTACT_TABLE_NAME,
                        /* wxChar      *dispCol1      */ wxT("NAME"),
                        /* wxChar      *dispCol2      */ wxT("JOINDATE"),
                        /* wxChar      *where         */ wxT(""),
                        /* wxChar      *orderBy       */ wxT("NAME"),
-                       /* bool      distinctValues */ TRUE);
+                       /* wxDb        *pDb           */ wxGetApp().READONLY_DB,
+                       /* const wxString &defDir     */ wxGetApp().DbConnectInf->GetDefaultDir(),
+                       /* bool        distinctValues */ TRUE);
 
         if (ListDB_Selection && wxStrlen(ListDB_Selection))
         {
             wxString w = wxT("NAME = '");
             w += ListDB_Selection;
             w += wxT("'");
 
         if (ListDB_Selection && wxStrlen(ListDB_Selection))
         {
             wxString w = wxT("NAME = '");
             w += ListDB_Selection;
             w += wxT("'");
-            GetRec((wxChar*) (const wxChar*) w);
+            GetRec(w);
         }
 
         return;
         }
 
         return;
@@ -883,7 +906,9 @@ bool CeditorDlg::Initialize()
 
     // Check if the table exists or not.  If it doesn't, ask the user if they want to 
     // create the table.  Continue trying to create the table until it exists, or user aborts
 
     // Check if the table exists or not.  If it doesn't, ask the user if they want to 
     // create the table.  Continue trying to create the table until it exists, or user aborts
-    while (!Contact->GetDb()->TableExists((wxChar *)CONTACT_TABLE_NAME,DbConnectInf.Uid,DbConnectInf.defaultDir))
+    while (!Contact->GetDb()->TableExists((wxChar *)CONTACT_TABLE_NAME, 
+                                          wxGetApp().DbConnectInf->GetUserID(), 
+                                          wxGetApp().DbConnectInf->GetDefaultDir()))
     {
         wxString tStr;
         tStr.Printf(wxT("Unable to open the table '%s'.\n\nTable may need to be created...?\n\n"),CONTACT_TABLE_NAME);
     {
         wxString tStr;
         tStr.Printf(wxT("Unable to open the table '%s'.\n\nTable may need to be created...?\n\n"),CONTACT_TABLE_NAME);
@@ -898,7 +923,7 @@ bool CeditorDlg::Initialize()
             return FALSE;
         }
         else
             return FALSE;
         }
         else
-            DemoFrame->CreateDataTable(TRUE);
+            wxGetApp().CreateDataTable(TRUE);
     }
 
     // Tables must be "opened" before anything other than creating/deleting table can be done
     }
 
     // Tables must be "opened" before anything other than creating/deleting table can be done
@@ -912,7 +937,7 @@ bool CeditorDlg::Initialize()
 // in the 2.4 release.  This check will determine whether the open failing was due
 // to the table not existing, or the users privileges being insufficient to
 // open the table.
 // in the 2.4 release.  This check will determine whether the open failing was due
 // to the table not existing, or the users privileges being insufficient to
 // open the table.
-        if (!Contact->GetDb()->TablePrivileges(CONTACT_TABLE_NAME,wxT("SELECT"),Contact->GetDb()->GetUsername(),Contact->GetDb()->GetUsername(),DbConnectInf.defaultDir))
+        if (!Contact->GetDb()->TablePrivileges(CONTACT_TABLE_NAME,wxT("SELECT"),Contact->GetDb()->GetUsername(),Contact->GetDb()->GetUsername(),DbConnectInf->GetDefaultDir()))
         {
             wxString tStr;
             tStr.Printf(wxT("Unable to open the table '%s'.\n\n"),CONTACT_TABLE_NAME);
         {
             wxString tStr;
             tStr.Printf(wxT("Unable to open the table '%s'.\n\n"),CONTACT_TABLE_NAME);
@@ -921,7 +946,8 @@ bool CeditorDlg::Initialize()
         }
         else 
 #endif
         }
         else 
 #endif
-        if (Contact->GetDb()->TableExists(CONTACT_TABLE_NAME,Contact->GetDb()->GetUsername(),DbConnectInf.defaultDir))
+        if (Contact->GetDb()->TableExists(CONTACT_TABLE_NAME, Contact->GetDb()->GetUsername(),
+                                          wxGetApp().DbConnectInf->GetDefaultDir()))
         {
             wxString tStr;
             tStr.Printf(wxT("Unable to open the table '%s'.\n\n"),CONTACT_TABLE_NAME);
         {
             wxString tStr;
             tStr.Printf(wxT("Unable to open the table '%s'.\n\n"),CONTACT_TABLE_NAME);
@@ -1004,9 +1030,9 @@ bool CeditorDlg::Initialize()
     
     if (Contact->GetDb()->Dbms() != dbmsPOSTGRES && Contact->GetDb()->Dbms() != dbmsMY_SQL)
     {
     
     if (Contact->GetDb()->Dbms() != dbmsPOSTGRES && Contact->GetDb()->Dbms() != dbmsMY_SQL)
     {
-        Contact->whereStr.sprintf(wxT("NAME = (SELECT MIN(NAME) FROM %s)"),Contact->GetTableName());
+        Contact->whereStr.Printf(wxT("NAME = (SELECT MIN(NAME) FROM %s)"),Contact->GetTableName());
         // NOTE: (const wxChar*) returns a pointer which may not be valid later, so this is short term use only
         // NOTE: (const wxChar*) returns a pointer which may not be valid later, so this is short term use only
-        Contact->SetWhereClause(Contact->whereStr.c_str());
+        Contact->SetWhereClause(Contact->whereStr);
     }
     else
        Contact->SetWhereClause(wxT(""));
     }
     else
        Contact->SetWhereClause(wxT(""));
@@ -1147,7 +1173,7 @@ bool CeditorDlg::GetData()
         return FALSE;
     }
 
         return FALSE;
     }
 
-    bool    invalid = FALSE;
+    bool   invalid = FALSE;
     int    mm,dd,yyyy;
     int    first, second;
 
     int    mm,dd,yyyy;
     int    first, second;
 
@@ -1281,7 +1307,8 @@ bool CeditorDlg::Save()
         }
         else  // mode == mEdit
         {
         }
         else  // mode == mEdit
         {
-            if (!Contact->Update())
+            Contact->whereStr.Printf("NAME = '%s'",saveName.c_str());
+            if (!Contact->UpdateWhere(Contact->whereStr))
             {
                 wxString tStr;
                 tStr  = wxT("Database update failed\n\n");
             {
                 wxString tStr;
                 tStr  = wxT("Database update failed\n\n");
@@ -1336,7 +1363,7 @@ bool CeditorDlg::GetNextRec()
     }
 
     w += wxT(")");
     }
 
     w += wxT(")");
-    return(GetRec((wxChar*) (const wxChar*) w));
+    return(GetRec(w));
 
 }  // CeditorDlg::GetNextRec()
 
 
 }  // CeditorDlg::GetNextRec()
 
@@ -1372,7 +1399,7 @@ bool CeditorDlg::GetPrevRec()
 
     w += wxT(")");
 
 
     w += wxT(")");
 
-    return(GetRec((wxChar*) (const wxChar*)w));
+    return(GetRec(w));
 
 }  // CeditorDlg::GetPrevRec()
 
 
 }  // CeditorDlg::GetPrevRec()
 
@@ -1381,7 +1408,7 @@ bool CeditorDlg::GetPrevRec()
  * This function is here to avoid duplicating this same code in both the
  * GetPrevRec() and GetNextRec() functions
  */
  * This function is here to avoid duplicating this same code in both the
  * GetPrevRec() and GetNextRec() functions
  */
-bool CeditorDlg::GetRec(wxChar *whereStr)
+bool CeditorDlg::GetRec(const wxString &whereStr)
 {
     Contact->SetWhereClause(whereStr);
     Contact->SetOrderByClause(wxT("NAME"));
 {
     Contact->SetWhereClause(whereStr);
     Contact->SetOrderByClause(wxT("NAME"));
@@ -1586,31 +1613,15 @@ bool CparameterDlg::GetData()
 
 bool CparameterDlg::Save()
 {
 
 bool CparameterDlg::Save()
 {
-    Cparameters saveParams = wxGetApp().params;
+    // Copy the current params in case user cancels changing
+    // the params, so that we can reset them.
     if (!GetData())
     {
     if (!GetData())
     {
-        wxGetApp().params = saveParams;
-        return FALSE;
-    }
-
-    FILE *paramFile;
-    if ((paramFile = fopen(paramFilename, wxT("wt"))) == NULL)
-    {
-        wxString tStr;
-        tStr.Printf(wxT("Unable to write/overwrite '%s'."),paramFilename);
-        wxMessageBox(tStr,wxT("File I/O Error..."),wxOK | wxICON_EXCLAMATION);
+        wxGetApp().params = savedParamSettings;
         return FALSE;
     }
 
         return FALSE;
     }
 
-    fputs(wxGetApp().params.ODBCSource, paramFile);
-    fputc(wxT('\n'), paramFile);
-    fputs(wxGetApp().params.UserName, paramFile);
-    fputc(wxT('\n'), paramFile);
-    fputs(wxGetApp().params.Password, paramFile);
-    fputc(wxT('\n'), paramFile);
-    fputs(wxGetApp().params.DirPath, paramFile);
-    fputc(wxT('\n'), paramFile);
-    fclose(paramFile);
+    wxGetApp().WriteParamFile(wxGetApp().params);
 
     return TRUE;
 }  // CparameterDlg::Save()
 
     return TRUE;
 }  // CparameterDlg::Save()
@@ -1622,7 +1633,8 @@ void CparameterDlg::FillDataSourceList()
     wxChar DsDesc[255];
     wxStringList strList;
 
     wxChar DsDesc[255];
     wxStringList strList;
 
-    while (wxDbGetDataSource(DbConnectInf.Henv, Dsn, SQL_MAX_DSN_LENGTH+1, DsDesc, 255))
+    while (wxDbGetDataSource(wxGetApp().DbConnectInf->GetHenv(), Dsn,
+                             SQL_MAX_DSN_LENGTH+1, DsDesc, 255))
         strList.Add(Dsn);
 
     strList.Sort();
         strList.Add(Dsn);
 
     strList.Sort();
@@ -2112,7 +2124,9 @@ void CqueryDlg::ProcessCountBtn()
 
     if (dbTable == 0)  // wxDbTable object needs to be created and opened
     {
 
     if (dbTable == 0)  // wxDbTable object needs to be created and opened
     {
-        if (!(dbTable = new wxDbTable(pDB, masterTableName, 0, wxT(""), !wxDB_QUERY_ONLY, DbConnectInf.defaultDir)))
+        if (!(dbTable = new wxDbTable(pDB, masterTableName, 0, wxT(""),
+                                      !wxDB_QUERY_ONLY, 
+                                      wxGetApp().DbConnectInf->GetDefaultDir())))
         {
             wxMessageBox(wxT("Memory allocation failed creating a wxDbTable object."),wxT("Error..."),wxOK | wxICON_EXCLAMATION);
             return;
         {
             wxMessageBox(wxT("Memory allocation failed creating a wxDbTable object."),wxT("Error..."),wxOK | wxICON_EXCLAMATION);
             return;
index d8405027703d5e82cf8a3ae7fa00103b9f12fad2..59d56bbdf0ccdf1bcc7d7ed750b35e65f879ff5c 100644 (file)
@@ -29,17 +29,21 @@ enum    DialogModes {mView,mCreate,mEdit,mSearch};
 
 // this seems to be missing, Robert Roebling (?)
 #ifndef MAX_PATH
 
 // this seems to be missing, Robert Roebling (?)
 #ifndef MAX_PATH
-#define MAX_PATH   200
+    #if defined(__WXMAC__)
+        #define MAX_PATH   260 /* max. length of full pathname */
+    #else  /* _MAC */
+        #define MAX_PATH   256 /* max. length of full pathname */
+    #endif
 #endif
 
 // Name of the table to be created/opened
 #endif
 
 // Name of the table to be created/opened
-const wxChar      CONTACT_TABLE_NAME[]        =    "contacts";
+const wxChar     CONTACT_TABLE_NAME[]       = "contacts";
 
 
-// Nuber of columns in the above table
-const int       CONTACT_NO_COLS            = 12;        // 0-11
+// Number of columns in the CONTACT table
+const int        CONTACT_NO_COLS            = 12;        // 0-11
+
+const wxChar     PARAM_FILENAME[]            = "dbtest.cfg";
 
 
-// Global structure for holding ODBC connection information
-struct wxDbConnectInf  DbConnectInf;
 
 enum Language {langENGLISH, langFRENCH, langGERMAN, langSPANISH, langOTHER};
 
 
 enum Language {langENGLISH, langFRENCH, langGERMAN, langSPANISH, langOTHER};
 
@@ -47,26 +51,23 @@ enum Language {langENGLISH, langFRENCH, langGERMAN, langSPANISH, langOTHER};
 class CeditorDlg;
 class CparameterDlg;
 
 class CeditorDlg;
 class CparameterDlg;
 
-const wxChar paramFilename[] = "dbtest.cfg";
-
-
-/*
- * This class contains the actual data members that are used for transferring
- * data back and forth from the database to the program.  
- *
- * NOTE: The object described in this class is just for example purposes, and has no
- * real meaning other than to show each type of field being used by the database
- */
+//
+// This class contains the actual data members that are used for transferring
+// data back and forth from the database to the program.  
+//
+// NOTE: The object described in this class is just for example purposes, and has no
+// real meaning other than to show each type of field being used by the database
+//
 class CstructContact : public wxObject
 {
     public:
 class CstructContact : public wxObject
 {
     public:
-        wxChar               Name[50+1];          //    Contact's name
-        wxChar               Addr1[50+1];
-        wxChar               Addr2[50+1];
-        wxChar               City[25+1];
-        wxChar               State[25+1];
-        wxChar               PostalCode[15+1];
-        wxChar               Country[20+1];
+        wxChar             Name[50+1];          //    Contact's name
+        wxChar             Addr1[50+1];
+        wxChar             Addr2[50+1];
+        wxChar             City[25+1];
+        wxChar             State[25+1];
+        wxChar             PostalCode[15+1];
+        wxChar             Country[20+1];
         TIMESTAMP_STRUCT   JoinDate;            // Date on which this person joined the wxWindows project
         Language           NativeLanguage;      // Enumerated type indicating person's native language
         bool               IsDeveloper;         // Is this person a developer for wxWindows, or just a subscriber
         TIMESTAMP_STRUCT   JoinDate;            // Date on which this person joined the wxWindows project
         Language           NativeLanguage;      // Enumerated type indicating person's native language
         bool               IsDeveloper;         // Is this person a developer for wxWindows, or just a subscriber
@@ -76,49 +77,62 @@ class CstructContact : public wxObject
 
 
 //
 
 
 //
-// NOTE: Ccontact inherits wxDbTable, which gives access to all the database functionality
+// The Ccontact class derives from wxDbTable, so we have access to all
+// of the database table functions and the local memory variables that
+// the database classes will store the data into (and read the data from)
+// all combined in this one class.
 //
 class Ccontact : public wxDbTable, public CstructContact
 { 
     private:
 //
 class Ccontact : public wxDbTable, public CstructContact
 { 
     private:
+        // Used to keep track of whether this class had a wxDb instance
+        // passed in to it or not.  If an existing wxDb instance was not 
+        // passed in at Ccontact creation time, then when the Ccontact
+        // instance is deleted, the connection will be freed as Ccontact
+        // created its own connection when it was created.
         bool                 freeDbConn;
         bool                 freeDbConn;
+
+        // Calls wxDbTable::SetColDefs() once for each column that is
+        // to be associated with some member variable for use with
+        // this database object.
         void                 SetupColumns();
 
     public:
         void                 SetupColumns();
 
     public:
+        // Used in places where we need to construct a WHERE clause to 
+        // be passed to the SetWhereClause() function.  From example,
+        // where building the WHERE clause requires using ::Printf()
+        // to build the string.
         wxString             whereStr;
         wxString             whereStr;
-        wxString             qryWhereStr;   // Where string returned from the query dialog
+
+        // WHERE string returned from the query dialog
+        wxString             qryWhereStr;
 
         Ccontact(wxDb *pwxDb=NULL);
         ~Ccontact();
 
         void                 Initialize();
 
         Ccontact(wxDb *pwxDb=NULL);
         ~Ccontact();
 
         void                 Initialize();
+
+        // Contains all the index definitions and calls to wxDbTable::CreateIndex()
+        // required to create all the indexes we wish to define for this table.
         bool                 CreateIndexes(void);
         bool                 CreateIndexes(void);
-        bool                 FetchByName(wxChar *name);
+
+        // Since we do not wish to have duplicate code blocks all over our program
+        // for a common query/fetch that we will need to do in many places, we
+        // include this member function that does it all for us in one place.
+        bool                 FetchByName(const wxString &name);
 
 };  // Ccontact class definition
 
 
 typedef struct Cparameters
 {
 
 };  // Ccontact class definition
 
 
 typedef struct Cparameters
 {
-    // The length of these strings were arbitrarily picked, and are
-    // dependent on the OS and database engine you will be using.
-    wxChar    ODBCSource[100+1];
-    wxChar    UserName[25+1];
-    wxChar    Password[25+1];
+    wxChar    ODBCSource[SQL_MAX_DSN_LENGTH+1];
+    wxChar    UserName[SQL_MAX_USER_NAME_LEN+1];
+    wxChar    Password[SQL_MAX_AUTHSTR_LEN+1];
     wxChar    DirPath[MAX_PATH+1];
 } Cparameters;
 
 
     wxChar    DirPath[MAX_PATH+1];
 } Cparameters;
 
 
-// Define a new application type
-class DatabaseDemoApp: public wxApp
-{
-    public:
-        Cparameters  params;
-        bool         OnInit();
-};  // DatabaseDemoApp
-
-DECLARE_APP(DatabaseDemoApp)
-
 // Define a new frame type
 class DatabaseDemoFrame: public wxFrame
 { 
 // Define a new frame type
 class DatabaseDemoFrame: public wxFrame
 { 
@@ -137,7 +151,6 @@ class DatabaseDemoFrame: public wxFrame
         void    OnEditParameters(wxCommandEvent& event);
         void    OnAbout(wxCommandEvent& event);
 
         void    OnEditParameters(wxCommandEvent& event);
         void    OnAbout(wxCommandEvent& event);
 
-        void    CreateDataTable(bool recreate);
         void    BuildEditorDialog();
         void    BuildParameterDialog(wxWindow *parent);
 
         void    BuildEditorDialog();
         void    BuildParameterDialog(wxWindow *parent);
 
@@ -145,13 +158,73 @@ DECLARE_EVENT_TABLE()
 };  // DatabaseDemoFrame
 
 
 };  // DatabaseDemoFrame
 
 
+// Define a new application type
+class DatabaseDemoApp: public wxApp
+{
+    public:
+        // These are the parameters that are stored in the "PARAM_FILENAME" file
+        // that are read in at startup of the program that indicate the connection
+        // parameters to be used for connecting to the ODBC data source.
+        Cparameters      params;
+
+        // Pointer to the main frame used by the App
+        DatabaseDemoFrame *DemoFrame;
+
+        // Pointer to the main database connection used in the program.  This
+        // pointer would normally be used for doing things as database lookups
+        // for user login names and passwords, getting workstation settings, etc.
+        //         
+        // ---> IMPORTANT <---
+        // 
+        // For each database object created which uses this wxDb pointer
+        // connection to the database, when a CommitTrans() or RollBackTrans()
+        // will commit or rollback EVERY object which uses this wxDb pointer.
+        // 
+        // To allow each table object (those derived from wxDbTable) to be 
+        // individually committed or rolled back, you MUST use a different
+        // instance of wxDb in the constructor of the table.  Doing so creates 
+        // more overhead, and will use more database connections (some DBs have
+        // connection limits...), so use connections sparringly.
+        // 
+        // It is recommended that one "main" database connection be created for
+        // the entire program to use for READ-ONLY database accesses, but for each
+        // table object which will do a CommitTrans() or RollbackTrans() that a
+        // new wxDb object be created and used for it.
+        wxDb            *READONLY_DB;
+
+        // Contains the ODBC connection information used by 
+        // all database connections
+        wxDbConnectInf  *DbConnectInf;
+
+        bool             OnInit();
+
+        // Read/Write ODBC connection parameters to the "PARAM_FILENAME" file
+        bool             ReadParamFile(Cparameters &params);
+        bool             WriteParamFile(Cparameters &params);
+
+        void             CreateDataTable(bool recreate);
+};  // DatabaseDemoApp
+
+
+DECLARE_APP(DatabaseDemoApp)
+
 
 // *************************** CeditorDlg ***************************
 
 class CeditorDlg : public wxPanel
 {
     private:
 
 // *************************** CeditorDlg ***************************
 
 class CeditorDlg : public wxPanel
 {
     private:
+        // Used to indicate whether all of the widget pointers (defined
+        // below) have been initialized to point to the memory for 
+        // the named widget.  Used as a safeguard from using the widget
+        // before it has been initialized.
         bool             widgetPtrsSet;
         bool             widgetPtrsSet;
+
+        // Used when the EDIT button has been pressed to maintain the 
+        // original name that was displayed in the editor before the 
+        // EDIT button was pressed, so that if CANCEL is pressed, a
+        // FetchByName() can be done to retrieve the original data
+        // to repopulate the dialog.
         wxString         saveName;
 
         // Pointers to all widgets on the dialog
         wxString         saveName;
 
         // Pointers to all widgets on the dialog
@@ -167,9 +240,16 @@ class CeditorDlg : public wxPanel
         wxStaticText    *pNativeLangMsg;
 
     public:
         wxStaticText    *pNativeLangMsg;
 
     public:
+        // Indicates if the editor dialog has been initialized yet (used to
+        // help trap if the Initialize() function failed to load all required
+        // resources or not.
         bool             initialized;
         bool             initialized;
+
         enum DialogModes mode;
         enum DialogModes mode;
-        Ccontact        *Contact;    // this is the table object that will be being manipulated
+
+        // Pointer to the wxDbTable instance that is used to manipulate
+        // the data in memory and in the database
+        Ccontact        *Contact;
 
         CeditorDlg(wxWindow *parent);
 
 
         CeditorDlg(wxWindow *parent);
 
@@ -179,14 +259,32 @@ class CeditorDlg : public wxPanel
         void    OnActivate(bool) {};  // necessary for hot keys
 
         bool    Initialize();
         void    OnActivate(bool) {};  // necessary for hot keys
 
         bool    Initialize();
+
+        // Sets wxStaticText fields to be editable or not depending
+        // on the current value of 'mode'
         void    FieldsEditable();
         void    FieldsEditable();
+
+        // Sets the editor mode, determining what state widgets
+        // on the dialog are to be in based on the operation
+        // being performed.
         void    SetMode(enum DialogModes m);
         void    SetMode(enum DialogModes m);
+
+        // Update/Retrieve data from the widgets on the dialog
         bool    PutData();
         bool    GetData();
         bool    PutData();
         bool    GetData();
+
+        // Inserts/updates the database with the current data
+        // retrieved from the editor dialog
         bool    Save();
         bool    Save();
+
+        // Database functions for changing the data that is to 
+        // be displayed on the dialog.  GetNextRec()/GetPrevRec()
+        // provide database independent methods that do not require
+        // backward scrolling cursors to obtain the record that
+        // is prior to the current record in the search sequence.
         bool    GetNextRec();
         bool    GetPrevRec();
         bool    GetNextRec();
         bool    GetPrevRec();
-        bool    GetRec(wxChar *whereStr);
+        bool    GetRec(const wxString &whereStr);
         
 DECLARE_EVENT_TABLE()
 };  // CeditorDlg
         
 DECLARE_EVENT_TABLE()
 };  // CeditorDlg
@@ -238,9 +336,19 @@ DECLARE_EVENT_TABLE()
 class CparameterDlg : public wxDialog
 {
     private:
 class CparameterDlg : public wxDialog
 {
     private:
+        // Used to indicate whether all of the widget pointers (defined
+        // below) have been initialized to point to the memory for 
+        // the named widget.  Used as a safeguard from using the widget
+        // before it has been initialized.
         bool                 widgetPtrsSet;
         bool                 widgetPtrsSet;
+
         enum DialogModes     mode;
         enum DialogModes     mode;
+
+        // Have the parameters been saved yet, or do they 
+        // need to be saved to update the params on disk
         bool                 saved;
         bool                 saved;
+
+        // Original params
         Cparameters          savedParamSettings;
 
         // Pointers to all widgets on the dialog
         Cparameters          savedParamSettings;
 
         // Pointers to all widgets on the dialog
@@ -258,9 +366,16 @@ class CparameterDlg : public wxDialog
         void    OnCommand(wxWindow& win, wxCommandEvent& event);
         void    OnActivate(bool) {};  // necessary for hot keys
 
         void    OnCommand(wxWindow& win, wxCommandEvent& event);
         void    OnActivate(bool) {};  // necessary for hot keys
 
+        // Update/Retrieve data from the widgets on the dialog
         bool    PutData();
         bool    GetData();
         bool    PutData();
         bool    GetData();
+
+        // Stores the defined parameter for connecting to the selected ODBC
+        // data source to the config file name in "PARAM_FILENAME"
         bool    Save();
         bool    Save();
+
+        // Populates the 'pParamODBCSourceList' listbox with the names of all
+        // ODBC datasource defined for use at the current workstation
         void    FillDataSourceList();
 
 DECLARE_EVENT_TABLE()
         void    FillDataSourceList();
 
 DECLARE_EVENT_TABLE()
@@ -313,13 +428,17 @@ wxChar * const langQRY_BETWEEN      = "column BETWEEN value AND value";
 class CqueryDlg : public wxDialog
 {
     private:
 class CqueryDlg : public wxDialog
 {
     private:
-        wxDbColInf  *colInf;        // Column inf. returned by db->GetColumns()
-        wxDbTable   *dbTable;
-        wxChar        *masterTableName;
-        wxChar        *pWhere;        // A pointer to the storage for the resulting where clause
+        wxDbColInf  *colInf;            // Column inf. returned by db->GetColumns()
+        wxDbTable   *dbTable;           // generic wxDbTable object for attaching to the table to query
+        wxChar      *masterTableName;   // Name of the table that 'dbTable' will be associated with
+        wxChar      *pWhere;            // A pointer to the storage for the resulting where clause
         wxDb        *pDB;
 
     public:
         wxDb        *pDB;
 
     public:
+        // Used to indicate whether all of the widget pointers (defined
+        // below) have been initialized to point to the memory for 
+        // the named widget.  Used as a safeguard from using the widget
+        // before it has been initialized.
         bool                     widgetPtrsSet;
 
         // Widget pointers
         bool                     widgetPtrsSet;
 
         // Widget pointers
index 7e6ff1b6c48f20ac32bd3ea73006c4d8e9a2fd92..e5959ab25512e01f4ec247b616a1aed7c95ecf71 100644 (file)
 extern wxDbList WXDLLEXPORT *PtrBegDbList;    /* from db.cpp, used in getting back error results from db connections */
 
 #include "listdb.h"
 extern wxDbList WXDLLEXPORT *PtrBegDbList;    /* from db.cpp, used in getting back error results from db connections */
 
 #include "listdb.h"
-
-// Global structure for holding ODBC connection information
-extern wxDbConnectInf DbConnectInf;
-
-// Global database connection
-extern wxDb *READONLY_DB;
-
+//#include "dbtest.h"
 
 // Used for passing the selected listbox selection back to the calling
 // routine.  This variable must be declared as 'extern' in the calling
 
 // Used for passing the selected listbox selection back to the calling
 // routine.  This variable must be declared as 'extern' in the calling
@@ -80,6 +74,8 @@ wxChar ListDB_Selection2[LOOKUP_COL_LEN+1];
 const int LISTDB_NO_SPACES_BETWEEN_COLS = 3;
 
 
 const int LISTDB_NO_SPACES_BETWEEN_COLS = 3;
 
 
+extern wxApp *DatabaseDemoApp;
+
 
 /*
  * This function will return the exact string(s) from the database engine
 
 /*
  * This function will return the exact string(s) from the database engine
@@ -143,8 +139,9 @@ const wxChar *GetExtendedDBErrorMsg2(wxChar *ErrFile, int ErrLine)
 
 
 // Clookup constructor
 
 
 // Clookup constructor
-Clookup::Clookup(wxChar *tblName, wxChar *colName) :
-     wxDbTable(READONLY_DB, tblName, 1, wxT(""), !wxDB_QUERY_ONLY, DbConnectInf.defaultDir)
+Clookup::Clookup(wxChar *tblName, wxChar *colName, wxDb *pDb, const wxString &defDir)
+   : wxDbTable(pDb, tblName, 1, wxT(""), !wxDB_QUERY_ONLY,
+               defDir)
 {
 
     SetColDefs (0, colName, DB_DATA_TYPE_VARCHAR, lookupCol, SQL_C_CHAR, LOOKUP_COL_LEN+1, FALSE, FALSE);
 {
 
     SetColDefs (0, colName, DB_DATA_TYPE_VARCHAR, lookupCol, SQL_C_CHAR, LOOKUP_COL_LEN+1, FALSE, FALSE);
@@ -153,9 +150,16 @@ Clookup::Clookup(wxChar *tblName, wxChar *colName) :
 
 
 // Clookup2 constructor
 
 
 // Clookup2 constructor
-Clookup2::Clookup2(wxChar *tblName, wxChar *colName1, wxChar *colName2, wxDb *pDb)
-   : wxDbTable(pDb, tblName, (1 + (wxStrlen(colName2) > 0)), NULL, !wxDB_QUERY_ONLY, DbConnectInf.defaultDir)
+Clookup2::Clookup2(wxChar *tblName, wxChar *colName1, wxChar *colName2,
+                   wxDb *pDb, const wxString &defDir)
+   : wxDbTable(pDb, tblName, (1 + (wxStrlen(colName2) > 0)), wxT(""),
+               !wxDB_QUERY_ONLY, defDir)
 {
 {
+    wxASSERT(pDb);
+    wxASSERT(tblName);
+    wxASSERT(colName1);
+    wxASSERT(colName2);
+
     int i = 0;
 
     SetColDefs (i, colName1, DB_DATA_TYPE_VARCHAR, lookupCol1, SQL_C_CHAR, LOOKUP_COL_LEN+1, FALSE, FALSE);
     int i = 0;
 
     SetColDefs (i, colName1, DB_DATA_TYPE_VARCHAR, lookupCol1, SQL_C_CHAR, LOOKUP_COL_LEN+1, FALSE, FALSE);
@@ -167,15 +171,17 @@ Clookup2::Clookup2(wxChar *tblName, wxChar *colName1, wxChar *colName2, wxDb *pD
 
 
 BEGIN_EVENT_TABLE(ClookUpDlg, wxDialog)
 
 
 BEGIN_EVENT_TABLE(ClookUpDlg, wxDialog)
-//     EVT_LISTBOX(LOOKUP_DIALOG_SELECT, ClookUpDlg::SelectCallback)
     EVT_BUTTON(LOOKUP_DIALOG_OK,  ClookUpDlg::OnButton)
     EVT_BUTTON(LOOKUP_DIALOG_CANCEL,  ClookUpDlg::OnButton)
     EVT_CLOSE(ClookUpDlg::OnClose)
 END_EVENT_TABLE()
 
     EVT_BUTTON(LOOKUP_DIALOG_OK,  ClookUpDlg::OnButton)
     EVT_BUTTON(LOOKUP_DIALOG_CANCEL,  ClookUpDlg::OnButton)
     EVT_CLOSE(ClookUpDlg::OnClose)
 END_EVENT_TABLE()
 
+
 // This is a generic lookup constructor that will work with any table and any column
 // This is a generic lookup constructor that will work with any table and any column
-ClookUpDlg::ClookUpDlg(wxWindow *parent, wxChar *windowTitle, wxChar *tableName, wxChar *colName,
-    wxChar *where, wxChar *orderBy)  : wxDialog (parent, LOOKUP_DIALOG, wxT("Select..."), wxPoint(-1, -1), wxSize(400, 290))
+ClookUpDlg::ClookUpDlg(wxWindow *parent, wxChar *windowTitle, wxChar *tableName,
+                       wxChar *colName, wxChar *where, wxChar *orderBy,
+                       wxDb *pDb, const wxString &defDir)
+   : wxDialog (parent, LOOKUP_DIALOG, wxT("Select..."), wxPoint(-1, -1), wxSize(400, 290))
 {
     wxBeginBusyCursor();
     
 {
     wxBeginBusyCursor();
     
@@ -186,14 +192,14 @@ ClookUpDlg::ClookUpDlg(wxWindow *parent, wxChar *windowTitle, wxChar *tableName,
     noDisplayCols = 1;
     col1Len = 0;
 
     noDisplayCols = 1;
     col1Len = 0;
 
-    pLookUpSelectList       = new wxListBox(this, LOOKUP_DIALOG_SELECT,                 wxPoint(  5,  15), wxSize(384, 195), 0, 0, wxLB_SINGLE|wxLB_ALWAYS_SB, wxDefaultValidator, wxT("LookUpSelectList"));
-    pLookUpOkBtn            = new wxButton(this, LOOKUP_DIALOG_OK,      wxT("&Ok"),     wxPoint(113, 222), wxSize( 70,  35), 0, wxDefaultValidator, wxT("LookUpOkBtn"));
-    pLookUpCancelBtn        = new wxButton(this, LOOKUP_DIALOG_CANCEL,  wxT("C&ancel"), wxPoint(212, 222), wxSize( 70,  35), 0, wxDefaultValidator, wxT("LookUpCancelBtn"));
+    pLookUpSelectList       = new wxListBox(this, LOOKUP_DIALOG_SELECT,                  wxPoint(  5,  15), wxSize(384, 195), 0, 0, wxLB_SINGLE|wxLB_ALWAYS_SB, wxDefaultValidator, wxT("LookUpSelectList"));
+    pLookUpOkBtn            = new wxButton(this,  LOOKUP_DIALOG_OK,      wxT("&Ok"),     wxPoint(113, 222), wxSize( 70,  35), 0, wxDefaultValidator, wxT("LookUpOkBtn"));
+    pLookUpCancelBtn        = new wxButton(this,  LOOKUP_DIALOG_CANCEL,  wxT("C&ancel"), wxPoint(212, 222), wxSize( 70,  35), 0, wxDefaultValidator, wxT("LookUpCancelBtn"));
 
     widgetPtrsSet = TRUE;
 
     // Query the lookup table and display the result set
 
     widgetPtrsSet = TRUE;
 
     // Query the lookup table and display the result set
-    if (!(lookup = new Clookup(tableName, colName)))
+    if (!(lookup = new Clookup(tableName, colName, pDb, defDir)))
     {
         wxMessageBox(wxT("Error allocating memory for 'Clookup'object."),wxT("Error..."));
         Close();
     {
         wxMessageBox(wxT("Error allocating memory for 'Clookup'object."),wxT("Error..."));
         Close();
@@ -263,13 +269,15 @@ ClookUpDlg::ClookUpDlg(wxWindow *parent, wxChar *windowTitle, wxChar *tableName,
 // since it cannot be derived when you query using your own sql statement.
 //
 // The optional database connection can be used if you'd like the lookup class
 // since it cannot be derived when you query using your own sql statement.
 //
 // The optional database connection can be used if you'd like the lookup class
-// to use a database pointer other than the global READONLY_DB.  This is necessary if
+// to use a database pointer other than wxGetApp().READONLY_DB.  This is necessary if
 // records are being saved, but not committed to the db, yet should be included
 // in the lookup window.
 //
 ClookUpDlg::ClookUpDlg(wxWindow *parent, wxChar *windowTitle, wxChar *tableName,
 // records are being saved, but not committed to the db, yet should be included
 // in the lookup window.
 //
 ClookUpDlg::ClookUpDlg(wxWindow *parent, wxChar *windowTitle, wxChar *tableName,
-    wxChar *dispCol1, wxChar *dispCol2, wxChar *where, wxChar *orderBy, bool distinctValues,
-    wxChar *selectStmt, int maxLenCol1, wxDb *pDb, bool allowOk)  : wxDialog (parent, LOOKUP_DIALOG, wxT("Select..."), wxPoint(-1, -1), wxSize(400, 290))
+                       wxChar *dispCol1, wxChar *dispCol2, wxChar *where, wxChar *orderBy,
+                       wxDb *pDb, const wxString &defDir, bool distinctValues, 
+                       wxChar *selectStmt, int maxLenCol1, bool allowOk)
+   : wxDialog (parent, LOOKUP_DIALOG, wxT("Select..."), wxPoint(-1, -1), wxSize(400, 290))
 {
     wxBeginBusyCursor();
     
 {
     wxBeginBusyCursor();
     
@@ -295,7 +303,7 @@ ClookUpDlg::ClookUpDlg(wxWindow *parent, wxChar *windowTitle, wxChar *tableName,
     widgetPtrsSet = TRUE;
 
     // Query the lookup table and display the result set
     widgetPtrsSet = TRUE;
 
     // Query the lookup table and display the result set
-    if (!(lookup2 = new Clookup2(tableName, dispCol1, dispCol2, pDb)))
+    if (!(lookup2 = new Clookup2(tableName, dispCol1, dispCol2, pDb, defDir)))
     {
         wxMessageBox(wxT("Error allocating memory for 'Clookup2' object."),wxT("Error..."));
         Close();
     {
         wxMessageBox(wxT("Error allocating memory for 'Clookup2' object."),wxT("Error..."));
         Close();
index d3c472498fbc91fe03682aa2b364b39f98d7f170..82897c2bb22a84dd8c92ba3cb077811c42988b3e 100644 (file)
@@ -25,9 +25,6 @@
 
 const int LOOKUP_COL_LEN = 250;
 
 
 const int LOOKUP_COL_LEN = 250;
 
-// Global database connection
-extern wxDb *READONLY_DB;
-
 // Clookup class
 class Clookup : public wxDbTable
 {
 // Clookup class
 class Clookup : public wxDbTable
 {
@@ -35,10 +32,11 @@ class Clookup : public wxDbTable
 
         wxChar lookupCol[LOOKUP_COL_LEN+1];
 
 
         wxChar lookupCol[LOOKUP_COL_LEN+1];
 
-        Clookup(wxChar *tblName, wxChar *colName);
+        Clookup(wxChar *tblName, wxChar *colName, wxDb *pDb, const wxString &defDir="");
 
 };  // Clookup
 
 
 };  // Clookup
 
+
 // Clookup2 class
 class Clookup2 : public wxDbTable
 {
 // Clookup2 class
 class Clookup2 : public wxDbTable
 {
@@ -47,10 +45,12 @@ class Clookup2 : public wxDbTable
         wxChar lookupCol1[LOOKUP_COL_LEN+1];
         wxChar lookupCol2[LOOKUP_COL_LEN+1];
 
         wxChar lookupCol1[LOOKUP_COL_LEN+1];
         wxChar lookupCol2[LOOKUP_COL_LEN+1];
 
-        Clookup2(wxChar *tblName, wxChar *colName1, wxChar *colName2, wxDb *pDb);
+        Clookup2(wxChar *tblName, wxChar *colName1, wxChar *colName2, wxDb *pDb, const wxString &defDir="");
 
 };  // Clookup2
 
 
 };  // Clookup2
 
+
+// ClookUpDlg class
 class ClookUpDlg : public wxDialog
 {
     private:
 class ClookUpDlg : public wxDialog
 {
     private:
@@ -73,14 +73,16 @@ class ClookUpDlg : public wxDialog
                     wxChar  *tableName,
                     wxChar  *colName,
                     wxChar  *where,
                     wxChar  *tableName,
                     wxChar  *colName,
                     wxChar  *where,
-                    wxChar  *orderBy);
+                    wxChar  *orderBy,
+                    wxDb    *pDb,
+                    const wxString &defDir);
 
         //
         // This is a generic lookup constructor that will work with any table and any column.
         // It extends the capabilites of the lookup dialog in the following ways:
         //
         //    1) 2 columns rather than one
 
         //
         // This is a generic lookup constructor that will work with any table and any column.
         // It extends the capabilites of the lookup dialog in the following ways:
         //
         //    1) 2 columns rather than one
-        // 2) The ability to select DISTINCT column values
+        //    2) The ability to select DISTINCT column values
         //
         // Only set distinctValues equal to true if necessary.  In many cases, the constraints
         // of the index(es) will enforce this uniqueness.  Selecting DISTINCT does require
         //
         // Only set distinctValues equal to true if necessary.  In many cases, the constraints
         // of the index(es) will enforce this uniqueness.  Selecting DISTINCT does require
@@ -95,8 +97,8 @@ class ClookUpDlg : public wxDialog
         // since it cannot be derived when you query using your own sql statement.
         //
         // The optional database connection can be used if you'd like the lookup class
         // since it cannot be derived when you query using your own sql statement.
         //
         // The optional database connection can be used if you'd like the lookup class
-        // to use a database pointer other than the global READONLY_DB.  This is necessary if
-        // records are being saved, but not committed to the db, yet should be included
+        // to use a database pointer other than the READONLY_DB of the app.  This is necessary
+        // if records are being saved, but not committed to the db, yet should be included
         // in the lookup window.
         //
         ClookUpDlg(wxWindow *parent,
         // in the lookup window.
         //
         ClookUpDlg(wxWindow *parent,
@@ -106,10 +108,11 @@ class ClookUpDlg : public wxDialog
                     wxChar  *dispCol2,                  // Optional
                     wxChar  *where,
                     wxChar  *orderBy,
                     wxChar  *dispCol2,                  // Optional
                     wxChar  *where,
                     wxChar  *orderBy,
+                    wxDb    *pDb,                       // Database connection pointer
+                    const wxString &defDir,
                     bool     distinctValues,            // e.g. SELECT DISTINCT ...
                     wxChar  *selectStmt = 0,            // If you wish to query by SQLstmt (complicated lookups)
                     int      maxLenCol1 = 0,            // Mandatory if querying by SQLstmt
                     bool     distinctValues,            // e.g. SELECT DISTINCT ...
                     wxChar  *selectStmt = 0,            // If you wish to query by SQLstmt (complicated lookups)
                     int      maxLenCol1 = 0,            // Mandatory if querying by SQLstmt
-                    wxDb    *pDb        = READONLY_DB,  // Database connection pointer
                     bool     allowOk    = TRUE);        // is the OK button enabled
 
         void        OnButton( wxCommandEvent &event );
                     bool     allowOk    = TRUE);        // is the OK button enabled
 
         void        OnButton( wxCommandEvent &event );
@@ -118,7 +121,7 @@ class ClookUpDlg : public wxDialog
         void        OnActivate(bool) {};  // necessary for hot keys
 
 DECLARE_EVENT_TABLE()
         void        OnActivate(bool) {};  // necessary for hot keys
 
 DECLARE_EVENT_TABLE()
-};
+};  // class ClookUpDlg
 
 #define LOOKUP_DIALOG                   500
 
 
 #define LOOKUP_DIALOG                   500