#include "stdafx.h" #include #include #include "columnst.h" #include "sesa.h" static CDatabase _db; static CString _strWorkDir; /////////////////////////////////////////////////////////// // SESA field info /////////////////////////////////////////////////////////// class SESA_Field : public CObject { CString m_strName; int m_nType; CString m_strValue; CTime m_tValue; double m_dValue; BOOL m_bValue; public: const CString& Name() const { return m_strName; } int Type() const { return m_nType; } CString& StrValue() { return m_strValue; } CTime& TimeValue() { return m_tValue; } double& DoubleValue() { return m_dValue; } BOOL& BoolValue() { return m_bValue; } SESA_Field(LPCSTR strName, int nType); virtual ~SESA_Field() { } }; SESA_Field::SESA_Field(LPCSTR strName, int nType) : m_strName(strName), m_nType(nType), m_bValue(FALSE), m_dValue(0.0) { } class SESA_FieldList : public CObject { CObList m_List; public: void Add(const CString& strField, int nType); POSITION GetHeadPosition() const; SESA_Field& GetNext(POSITION& rPosition); SESA_Field& Find(const CString& strField); void RemoveAll(); int GetCount() const { return m_List.GetCount(); } virtual ~SESA_FieldList(); }; void SESA_FieldList::Add(const CString& strName, int nType) { SESA_Field* pField = new SESA_Field(strName, nType); m_List.AddTail(pField); } POSITION SESA_FieldList::GetHeadPosition() const { return m_List.GetHeadPosition(); } SESA_Field& SESA_FieldList::GetNext(POSITION& rPosition) { SESA_Field* pField = (SESA_Field*)m_List.GetNext(rPosition); ASSERT(pField); return *pField; } SESA_Field& SESA_FieldList::Find(const CString& strName) { for (POSITION pos = GetHeadPosition(); pos;) { SESA_Field& fld = GetNext(pos); if (fld.Name() == strName) return fld; } return SESA_Field("", 0); } void SESA_FieldList::RemoveAll() { while (!m_List.IsEmpty()) { CObject* pField = m_List.RemoveHead(); delete pField; } } SESA_FieldList::~SESA_FieldList() { RemoveAll(); } /////////////////////////////////////////////////////////// // Sesa recordset /////////////////////////////////////////////////////////// class SESA_Recordset : public CRecordset { // DECLARE_DYNAMIC(SESA_Recordset) SESA_FieldList m_FieldList; CStringList m_DumpList; protected: virtual CString GetDefaultConnect(); virtual CString GetDefaultSQL(); virtual void DoFieldExchange(CFieldExchange* pFX); public: BOOL Open(LPCSTR strTable); void DumpHeader(ostream& out); void ReadDumpList(const CString& strFile); void DumpFields(ostream& out); SESA_Recordset(CDatabase* pDatabase); virtual ~SESA_Recordset() { } }; //IMPLEMENT_DYNAMIC(SESA_Recordset, CRecordset) CString SESA_Recordset::GetDefaultConnect() { return "ODBC;"; // Copied from CATALOG sample application } CString SESA_Recordset::GetDefaultSQL() { ASSERT(FALSE); // Copied from CATALOG sample application return "!"; } BOOL SESA_Recordset::Open(LPCSTR strTable) { CColumns Cols(&_db); Cols.m_strTableNameParam = strTable; BOOL ok = Cols.Open(CRecordset::forwardOnly, NULL, CRecordset::readOnly); if (ok) { while (!Cols.IsEOF()) { m_FieldList.Add(Cols.m_strColumnName, Cols.m_nDataType); Cols.MoveNext(); } RETCODE nRetCode; AFX_SQL_SYNC(::SQLFreeStmt(Cols.m_hstmt, SQL_CLOSE)); m_nFields = m_FieldList.GetCount(); } if (ok) { ok = CRecordset::Open(CRecordset::snapshot, strTable, CRecordset::readOnly); if (!ok) { CString msg; msg = "Can't open table "; msg += strTable; AfxMessageBox(msg, MB_OK | MB_ICONEXCLAMATION); } } return ok; } void SESA_Recordset::DoFieldExchange(CFieldExchange* pFX) { pFX->SetFieldType(CFieldExchange::outputColumn); BOOL bLoad= pFX->m_nOperation == CFieldExchange::Fixup; int nField = 1; for (POSITION pos = m_FieldList.GetHeadPosition(); pos; nField++) { SESA_Field& fld = m_FieldList.GetNext(pos); CString& val = fld.StrValue(); switch(fld.Type()) { case SQL_BIT: { BOOL& b = fld.BoolValue(); RFX_Bool(pFX, fld.Name(), b); if (bLoad) { if (b == FALSE || IsFieldFlagNull(nField, CFieldExchange::outputColumn)) val.Empty(); else val = "X"; } } break; case SQL_CHAR: case SQL_NUMERIC: RFX_Text(pFX, fld.Name(), val); break; case SQL_DATE: { CTime& t = fld.TimeValue(); RFX_Date(pFX, fld.Name(), t); if (bLoad) { TIMESTAMP_STRUCT* pts = (TIMESTAMP_STRUCT*)m_pvFieldProxy[nField]; if (pts->year == 0) val.Empty(); else { char* buf = val.GetBuffer(16); sprintf(buf, "%02d-%02d-%04d", pts->day, pts->month, pts->year); val.ReleaseBuffer(); } } } break; case SQL_DOUBLE: { double& d = fld.DoubleValue(); RFX_Double(pFX, fld.Name(), d); if (bLoad) { if (d == 0.0 || IsFieldFlagNull(nField, CFieldExchange::outputColumn)) { val.Empty(); } else { char* buf = val.GetBuffer(32); sprintf(buf, "%.12lg", d); val.ReleaseBuffer(); } } } break; default: ASSERT(0); break; } } } void SESA_Recordset::DumpHeader(ostream& out) { out << "[MAIN]" << endl << "TYPEFIELD=-1" << endl << "DECSEP=." << endl << "FIELDSEP=|" << endl << endl; out << "[RECORD]" << endl; int num = 0; for (POSITION pos = m_FieldList.GetHeadPosition(); pos; num++) { const SESA_Field& fld = m_FieldList.GetNext(pos); out << "NAME(" << num << ") = " << fld.Name() << endl << endl; } } void SESA_Recordset::ReadDumpList(const CString& strFile) { char szField[16]; char szName[16]; char szFile[32]; // Mette .\ davanti al nome per cercare nella directory corrente, // altrimenti lo cerca nella directory di Windows sprintf(szFile, ".\\%s", strFile); for (int num = 0; ; num++) { sprintf(szField, "NAME(%d)", num); GetPrivateProfileString("RECORD", szField, "", szName, sizeof(szName), szFile); if (*szName) m_DumpList.AddTail(szName); else break; } } void SESA_Recordset::DumpFields(ostream& out) { if (m_DumpList.IsEmpty()) { int num = 0; for (POSITION pos = m_FieldList.GetHeadPosition(); pos; num++) { SESA_Field& fld = m_FieldList.GetNext(pos); if (num) out << '|'; out << fld.StrValue(); } } else { int num = 0; for (POSITION npos = m_DumpList.GetHeadPosition(); npos; num++) { CString& strName = m_DumpList.GetNext(npos); SESA_Field& fld = m_FieldList.Find(strName); if (num) out << '|'; out << fld.StrValue(); } } out << endl; } SESA_Recordset::SESA_Recordset(CDatabase* pDatabase) : CRecordset(pDatabase) { } /////////////////////////////////////////////////////////// // SESA functions /////////////////////////////////////////////////////////// static BOOL UpdateODBCIni(LPCSTR szEntry, LPCSTR szDefault, BOOL bForce = FALSE) { BOOL bWrite = bForce; if (!bForce) { char szBuffer[80]; ::GetPrivateProfileString("SIGLAPP", szEntry, "", szBuffer, sizeof(szBuffer), "odbc.ini"); bWrite = *szBuffer == '\0'; } if (bWrite) ::WritePrivateProfileString("SIGLAPP", szEntry, szDefault, "odbc.ini"); return bWrite; } BOOL SESA_OpenDatabase(const char* lpszDSN, const char* lpszConnect) { if (lpszDSN == NULL || *lpszDSN == '\0') { lpszDSN = "SIGLAPP"; const char* SIGLAPP = getenv(lpszDSN); if (SIGLAPP) { UpdateODBCIni("Driver", "simba.dll"); UpdateODBCIni("Description", "Dati Comuni Sigla++"); UpdateODBCIni("FileType", "FoxPro 2.5"); UpdateODBCIni("DataDirectory", SIGLAPP, TRUE); UpdateODBCIni("SingleUser", "False"); } } if (lpszConnect == NULL || *lpszConnect == '\0') lpszConnect = "ODBC;"; // DataSrc Excl ReadOnly ConnectString BOOL ok = _db.Open(lpszDSN, FALSE, TRUE, lpszConnect); if (!ok) { CString msg; msg = "Can't connect to database "; msg += lpszDSN; msg += " using "; msg += lpszConnect; AfxMessageBox(msg, MB_OK | MB_ICONEXCLAMATION); } return ok; } BOOL SESA_CloseDatabase() { if (_db.IsOpen()) _db.Close(); return TRUE; } BOOL SESA_DumpTable(const char* lpszTableName) { const BOOL bWasOpen = _db.IsOpen(); if (!bWasOpen) { BOOL bOk = SESA_OpenDatabase(); if (!bOk) return FALSE; } SESA_Recordset rs(&_db); BOOL ok = rs.Open(lpszTableName); if (ok) { CString strName = _strWorkDir; strName += lpszTableName; strName += ".ini"; if (access(strName, 0x00) == 0) { rs.ReadDumpList(strName); } else { ofstream out(strName); rs.DumpHeader(out); } strName = _strWorkDir; strName += lpszTableName; strName += ".txt"; ofstream out(strName); while (!rs.IsEOF()) { rs.DumpFields(out); rs.MoveNext(); } RETCODE nRetCode; AFX_SQL_SYNC(::SQLFreeStmt(rs.m_hstmt, SQL_CLOSE)); } else { CString msg; msg = "Can't open table "; msg += lpszTableName; AfxMessageBox(msg, MB_OK | MB_ICONEXCLAMATION); } if (!bWasOpen) SESA_CloseDatabase(); return ok; } BOOL SESA_WorkDir(const char* strDir) { _strWorkDir = strDir; _strWorkDir = _strWorkDir.SpanExcluding(" "); const char& last = _strWorkDir[_strWorkDir.GetLength()-1]; if (last != '\\' && last != '/') _strWorkDir += "\\"; return !_strWorkDir.IsEmpty(); }