2 messages in com.mysql.lists.plusplusMySql++ Wrapper
FromSent OnAttachments
Kalada Sogbetun13 Apr 2003 03:24 
Kalada Sogbetun13 Apr 2003 03:24 
Subject:MySql++ Wrapper
From:Kalada Sogbetun (fkso@yahoo.com)
Date:04/13/2003 03:24:14 AM
List:com.mysql.lists.plusplus

I am involved in writing an application that accesses a MySql database on a website.

I initially wrote the program using a MySql ODBC driver. Access to the database was through CRecordset using a DSN.

Later I decided to change to MySql++ for security reasons.

Instead of changing all my code (there are several tables in the database accessed all over the program) I decided to write a MySql++ wrapper that would present the program a minimal CRecordset interface. Implement just the parts I need.

The structure I ended up with comprises of a base class CSqlRecordset which is a template class and is also an abstract class.

The database class derives from this and use the sql_create() generated struct as the template variable. This is demonstrated below.

MySqlW.h

//Class CSqlRecordset template <class T> class CSqlRecordset { private: // Data Members BOOL DBOpen, mBOF, mEOF ; Connection *con ; Query *que ; vector <T> res ; T* SaveR ;

// Connection CString m_Username, m_Host, m_Password, m_dbname ;

public: CSqlRecordset(void) ; CSqlRecordset(CString Username, CString Password, CString Host) ; ~CSqlRecordset(void) ;

// Data Members vector<T>::iterator i ; BOOL AddingNew, Editing ; T dbVars ; CString m_strFilter, m_pDatabase , m_DeleteStr; int m_nFields ; int m_NParams ;

void Close(void) ; int Open(void) ;

void SetUsername(CString str) { m_Username = str ; } ; void SetPassword(CString str) { m_Password = str ; } ; void SetHost(CString str) { m_Host = str; } ; void SetDefaultDb(CString str) { m_dbname = str; } ;

// Attributes int GetRecordCount(void) ; BOOL IsOpen(void) { return DBOpen ; }; BOOL IsBOF(void) { return mBOF ; }; BOOL IsEOF(void) { return mEOF ; };

// Update Operations void AddNew(void) ; void Delete(void) ; void Update(void) ; void Edit(void) ;

// Navigation void MoveFirst(void) ; void MoveLast(void) ; void MovePrev(void) ; void MoveNext(void) ;

// Others void Requery(void) ; CString GetDefaultSQL(void) ; virtual void BuildDeleteStr(void) = 0 ; virtual void PopulateRecordset(BOOL = TRUE) = 0; } ;

TestDb1.h

//SqlCreate generated Struct sql_create_4(DBVARS, 1, 4, string,m_Firstname,string,m_Surname,double,m_Age,string,m_Address);

// CTestDb recordset class CTestDb : public CSqlRecordset<struct DBVARS> { public: CTestDb(void);

// Field/Param Data //{{AFX_FIELD(CTestDb, CRecordset) CString m_Firstname; CString m_Surname; long m_Age; CString m_Address; //}}AFX_FIELD // Overrides // ClassWizard generated virtual function overrides //{{AFX_VIRTUAL(CTestDb) public: //}}AFX_VIRTUAL // Implementation void BuildDeleteStr(void) ; void PopulateRecordset(BOOL = TRUE) ; };

My problem is that sql_create generates char *DBVARS::names[] = { "m_Firstname" , "m_Surname" , "m_Age" , "m_Address" }; char *DBVARS::_table = "DBVARS" ;

as part of the struct.

And since several files need to include TestDb.h I end up with the following error messages -

TestDb1.obj : error LNK2005: "public: static char * DBVARS::_table" (?_table@DBVARS@@2PADA) already defined in TestDb.obj

TestDb1.obj : error LNK2005: "public: static char * * DBVARS::names" (?names@DBVARS@@2PAPADA) already defined in TestDb.obj

TestDbDlg.obj : error LNK2005: "public: static char * DBVARS::_table" (?_table@DBVARS@@2PADA) already defined in TestDb.obj

TestDbDlg.obj : error LNK2005: "public: static char * * DBVARS::names" (?names@DBVARS@@2PAPADA) already defined in TestDb.obj

Pls Note - App name is TestDb (testdb.cpp) and Database Class name is CTestDb thus database is stored in file testdb1.cpp.

Can anyone suggest a way our of this?

Note - Reader beware - This is currently a rough hack to test feasibility.