#include "StdAfx.h" #include "sqlfile.h" #include "server.h" #include "tracing.h" #include "errno.h" #include "iserrors.h" BOOL TSqlFile::IsOpen() const { return m_nKey > 0; } int TSqlFile::TestOpen() const { int err = IsOpen() ? NOERR : _isnotopen; return err; } CdbTableDef TSqlFile::GetTableDef() const { TPrassiServer& s = GetServer(); return s.GetTableDef(m_nFirm, m_nLogicNumber); } CdbRecordset& TSqlFile::GetSnapshot() { TPrassiServer& s = GetServer(); if (m_dwSnapHandle == 0) { char sKey[4]; itoa(m_nKey, sKey, 10); const char* sWhere; if (m_strWhere.IsEmpty()) sWhere = NULL; else sWhere = m_strWhere; m_dwSnapHandle = s.OpenSnapshot(m_nFirm, m_nLogicNumber, sWhere, sKey); m_nItems = -1; } return s.GetSnapshot(m_dwSnapHandle); } BOOL TSqlFile::Requery() { BOOL bOk = IsOpen(); if (bOk && m_dwSnapHandle) { TPrassiServer& s = GetServer(); BOOL bUpdated = s.UpdateSnapshot(m_dwSnapHandle, m_nFirm, m_nLogicNumber); if (bUpdated) m_nItems = -1; } return bOk; } CdbRecordset& TSqlFile::GetDynaset() const { TPrassiServer& s = GetServer(); return s.GetDynaset(m_nFirm, m_nLogicNumber); } int TSqlFile::Open() { int err = NOERR; if (!IsOpen()) { if (m_bExists) { m_nKey = 1; m_nStatus = _isbof; } else err = ENOENT; } else err = _isalropen; return err; } void TSqlFile::CloseSnapshot() { if (m_dwSnapHandle) { TPrassiServer& s = GetServer(); s.CloseSnapshot(m_dwSnapHandle); m_dwSnapHandle = 0; m_nStatus = _isbof; } } int TSqlFile::Close() { int err = TestOpen(); if (err == NOERR) { UnlockAll(); CloseSnapshot(); m_nKey = 0; m_nStatus = _isnotopen; } return err; } BOOL TSqlFile::SetFirm(int nFirm) { BOOL bOk = TRUE; if (m_nFirm != nFirm) { TPrassiServer& s = GetServer(); bOk = s.OpenTableDef(nFirm, m_nLogicNumber); if (bOk) { CloseSnapshot(); s.CloseTableDef(m_nFirm, m_nLogicNumber); m_nFirm = nFirm; } } return bOk; } int TSqlFile::First(int nLock) { if (Requery()) { CdbRecordset& dbSnapshot = GetSnapshot(); try { dbSnapshot.MoveFirst(); m_nStatus = NOERR; } catch(...) { CloseSnapshot(); m_nStatus = _iseof; m_nItems = 0; } if (m_nStatus == NOERR && nLock) m_nStatus = HandleLock(dbSnapshot, nLock); } return m_nStatus; } const char* TSqlFile::VariantToString(const COleVariant& oleVariant) const { static char strBuffer[32]; switch(oleVariant.vt) { case VT_NULL: return ""; case VT_INT: case VT_I1: case VT_I2: case VT_I4: case VT_I8: sprintf(strBuffer, "%d", m_oleVariant.lVal); return strBuffer; case VT_UINT: case VT_UI1: case VT_UI2: case VT_UI4: case VT_UI8: sprintf(strBuffer, "%u", m_oleVariant.lVal); return strBuffer; case VT_R4: case VT_R8: sprintf(strBuffer, "%lg", m_oleVariant.dblVal); return strBuffer; case VT_BSTR: return (const char*)m_oleVariant.pbVal; default: break; } return NULL; } const char* TSqlFile::GetField(CdbRecordset& dbRecordset, const char* strName) { const char* val; try { m_oleVariant = dbRecordset.GetField(strName); val = VariantToString(m_oleVariant); } catch(...) { val = NULL; } return val; } const char* TSqlFile::GetField(const char* strName) { const char* val = NULL; if (IsOpen()) { CdbRecordset& dbSnapshot = GetSnapshot(); val = GetField(dbSnapshot, strName); } return val; } CString TSqlFile::GetFieldInfo(int pos) const { CString strInfo; try { CdbTableDef dbTable = GetTableDef(); if (pos >= 0 && pos < dbTable.Fields.GetCount()) { char buffer[32]; CdbField dbField = dbTable[pos]; strInfo = dbField.GetName(); TFieldtypes tType; switch (dbField.GetType()) { case dbBoolean : tType = _boolfld; break; case dbByte : tType = _charfld; break; case dbInteger : tType = _intfld; break; case dbLong : tType = _longfld; break; case dbCurrency : case dbSingle : case dbDouble : tType = _realfld; break; case dbDate : tType = _datefld; break; case dbText : tType = _alfafld; break; case dbMemo : tType = _memofld; break; default : tType = _nullfld; break; } strInfo += ","; strInfo += '0' + tType; itoa(dbField.GetSize(), buffer, 10); strInfo += ","; strInfo += buffer; strInfo += ",0"; // decimali } } catch(...) { strInfo = ""; } return strInfo; } int TSqlFile::GetKey() const { return m_nKey; } CString TSqlFile::GetKeyExpr(int key) const { CString strExpr; CdbTableDef dbTable = GetTableDef(); if (key > 0 && key <= dbTable.Indexes.GetCount()) { CdbIndex dbIndex = dbTable.Indexes[key-1]; CdbFields& idxFields = dbIndex.Fields; for (int f = 0; f < idxFields.GetCount(); f++) { if (f) strExpr += "+"; strExpr += idxFields[f].GetName(); } } return strExpr; } int TSqlFile::GetRecordCount() { int items = -1; if (IsOpen()) { CdbTableDef dbTable = GetTableDef(); items = dbTable.GetRecordCount(); } return items; } int TSqlFile::Last(int nLock) { if (Requery()) { CdbRecordset& dbSnapshot = GetSnapshot(); try { dbSnapshot.MoveLast(); m_nStatus = NOERR; m_nItems = dbSnapshot.GetAbsolutePosition()+1; } catch(...) { m_nStatus = _isbof; m_nItems = 0; } if (m_nStatus == NOERR && nLock) m_nStatus = HandleLock(dbSnapshot, nLock); } return m_nStatus; } int TSqlFile::Move(long pos, int nLock) { if (TestOpen() == NOERR) { if (pos == 0) { Requery(); m_nStatus = _isbof; } CdbRecordset& dbSnapshot = GetSnapshot(); try { if (m_nStatus == NOERR) { long cur = dbSnapshot.GetAbsolutePosition(); dbSnapshot.Move(pos-cur); } else { dbSnapshot.MoveFirst(); if (pos > 0) dbSnapshot.Move(pos); } m_nStatus = dbSnapshot.GetEOF() ? _iseof : NOERR; if (m_nStatus == NOERR && nLock) m_nStatus = HandleLock(dbSnapshot, nLock); } catch(...) { m_nStatus = pos >= 0 ? _iseof : _isbof; } } return m_nStatus; } int TSqlFile::Next(int nLock) { if (IsOpen()) { CdbRecordset& dbSnapshot = GetSnapshot(); try { dbSnapshot.MoveNext(); if (dbSnapshot.GetEOF()) m_nStatus = _iseof; else m_nStatus = NOERR; if (m_nStatus == NOERR && nLock) m_nStatus = HandleLock(dbSnapshot, nLock); } catch(...) { m_nStatus = _iseof; } } return m_nStatus; } long TSqlFile::GetPosition() { long pos = -1; if (m_nStatus == NOERR ) pos = GetSnapshot().GetAbsolutePosition(); return pos; } int TSqlFile::Prev(int nLock) { if (IsOpen()) { CdbRecordset& dbSnapshot = GetSnapshot(); try { dbSnapshot.MovePrevious(); if (dbSnapshot.GetBOF()) m_nStatus = _isbof; else m_nStatus = NOERR; if (m_nStatus == NOERR && nLock) m_nStatus = HandleLock(dbSnapshot, nLock); } catch(...) { m_nStatus = _isbof; } } return m_nStatus; } int TSqlFile::Skip(long pos, int nLock) { if (IsOpen()) { CdbRecordset& dbSnapshot = GetSnapshot(); try { dbSnapshot.Move(pos); if (pos >= 0) m_nStatus = dbSnapshot.GetEOF() ? _iseof : NOERR; else m_nStatus = dbSnapshot.GetBOF() ? _isbof : NOERR; if (m_nStatus == NOERR && nLock) m_nStatus = HandleLock(dbSnapshot, nLock); } catch(...) { m_nStatus = pos >= 0 ? _iseof : _isbof; } } return m_nStatus; } CString TSqlFile::BuildKey(CdbRecordset& dbRecordset, int nKey) { CdbTableDef dbTable = GetTableDef(); CdbIndex dbIndex = dbTable.Indexes[nKey-1]; CdbFields& idxFields = dbIndex.Fields; CString sKey, sName, sValue, sFormatted; for (int f = 0; f < idxFields.GetCount(); f++) { sName = idxFields[f].GetName(); sValue = GetField(dbRecordset, sName); const int nSize = dbRecordset[sName].GetSize(); if (sValue.GetLength() < nSize) { SHORT int nType = dbRecordset[sName].GetType(); if (nType == dbText) sFormatted.Format("%-*s", nSize, (const char*)sValue); else sFormatted.Format("%*s", nSize, (const char*)sValue); sKey += sFormatted; } else sKey += sValue; } return sKey; } CString TSqlFile::BuildKey(const TSqlRecord& sqlRecord, int nKey) { CdbTableDef dbTable = GetTableDef(); CdbIndex dbIndex = dbTable.Indexes[nKey-1]; CdbFields& idxFields = dbIndex.Fields; CString sKey, sName, sValue, sFormatted; for (int f = 0; f < idxFields.GetCount(); f++) { SHORT index = idxFields[f].GetOrdinalPosition(); sValue = sqlRecord.Get(index); const int nSize = dbTable[index].GetSize(); if (sValue.GetLength() < nSize) { SHORT int nType = dbTable[index].GetType(); if (nType == dbText) sFormatted.Format("%-*s", nSize, (const char*)sValue); else sFormatted.Format("%*s", nSize, (const char*)sValue); sKey += sFormatted; } else sKey += sValue; } return sKey; } int TSqlFile::Read(CdbRecordset& dbSet, const char* sKey, int flags) { int err = NOERR; if (m_nItems < 0) { try { dbSet.MoveLast(); m_nItems = dbSet.GetAbsolutePosition()+1; } catch(...) { m_nItems = 0; return _isemptyfile; } } const int nLast = m_nItems-1; int min = 0; int max = nLast; int cur = dbSet.GetAbsolutePosition(); CString sCurkey; int nCompare = +1; while (min <= max) { const int next = (min+max)/2; try { dbSet.Move(next-cur); cur = next; } catch(...) { cur = nLast; break; } sCurkey = BuildKey(dbSet, m_nKey); nCompare = strcmp(sCurkey, sKey); if (nCompare == 0) break; if (nCompare < 0) min = cur+1; else max = cur-1; } switch (flags & 0xFF) { case _isgteq: while (nCompare < 0 && cur < nLast) { dbSet.MoveNext(); cur++; sCurkey = BuildKey(dbSet, m_nKey); nCompare = strcmp(sCurkey, sKey); } err = nCompare >= 0 ? NOERR : _iseof; break; case _isgreat: while (nCompare <= 0 && cur < nLast) { dbSet.MoveNext(); cur++; sCurkey = BuildKey(dbSet, m_nKey); nCompare = strcmp(sCurkey, sKey); } err = nCompare > 0 ? NOERR : _iseof; break; default: err = nCompare == 0 ? NOERR : _iskeynotfound; break; } if (err == NOERR) err = HandleLock(dbSet, flags); return err; } int TSqlFile::Read(const char* sKey, int flags) { if (IsOpen()) m_nStatus = Read(GetSnapshot(), sKey, flags); return m_nStatus; } int TSqlFile::SetField(int index, const char* value) { return m_sqlRecord.Set((SHORT)index, value); } int TSqlFile::SetField(const char* name, const char* value) { int err; try { CdbTableDef dbTable = GetTableDef(); SHORT nIndex = dbTable[name].GetOrdinalPosition(); err = m_sqlRecord.Set(nIndex, value); } catch(...) { err = _iskeyerr; } return err; } int TSqlFile::SetKey(int nKey) { int err = TestOpen(); if (err == NOERR) { if (nKey != m_nKey) { CdbTableDef dbTable = GetTableDef(); if (nKey > 0 && nKey <= dbTable.Indexes.GetCount()) { m_nKey = nKey; CloseSnapshot(); } else err = _iskeyrangeerr; } } return err; } int TSqlFile::Remove(const char* sKey) { CdbRecordset& dbDynaset = GetDynaset(); int err = Read(dbDynaset, sKey, _isequal | _testandlock); if (err == NOERR) { Unlock(sKey); dbDynaset.Delete(); } return err; } int TSqlFile::Rewrite(const char* sKey) { CdbRecordset& dbDynaset = GetDynaset(); int err = Read(dbDynaset, sKey, _isequal | _testandlock); if (err == NOERR) { m_sqlRecord.SetRecord(dbDynaset); Unlock(sKey); } return err; } int TSqlFile::Write() { CdbRecordset& dbDynaset = GetDynaset(); int err = NOERR; try { dbDynaset.AddNew(); m_sqlRecord.SetRecord(dbDynaset); dbDynaset.Update(); } catch(...) { err = _isreinsert; } return err; } int TSqlFile::Lock(CdbRecordset& dbSnapshot) { CString strKey; strKey = BuildKey(dbSnapshot, 1); TPrassiServer& s = GetServer(); int err = s.Lock(m_nFirm, m_nLogicNumber, strKey, m_dwConnection); if (err == NOERR) m_Locks.SetAt(strKey, NULL); return err; } int TSqlFile::Unlock(LPCSTR sKey) { void* dummy; if (m_Locks.Lookup(sKey, dummy)) { TPrassiServer& s = GetServer(); s.Unlock(m_nFirm, m_nLogicNumber, sKey, m_dwConnection); m_Locks.RemoveKey(sKey); } return NOERR; } int TSqlFile::Unlock(CdbRecordset& dynaset) { CString strKey; strKey = BuildKey(dynaset, 1); return Unlock(strKey); } void TSqlFile::UnlockAll() { CString strKey; void* dummy; for (POSITION pos = m_Locks.GetStartPosition(); pos; ) { m_Locks.GetNextAssoc(pos, strKey, dummy); Unlock(strKey); } if (m_bExclusiveLock) ExclusiveUnlock(); } int TSqlFile::ClearFields() { int err = TestOpen(); if (err == NOERR) m_sqlRecord.Clear(); return err; } int TSqlFile::HandleLock(CdbRecordset& dbRecordset, int nLock) { int err = NOERR; if ((nLock & _lock) || (nLock & _testandlock)) err = Lock(dbRecordset); else { if (nLock & _unlock) err = Unlock(dbRecordset); } return err; } int TSqlFile::ExclusiveLock() { TPrassiServer& s = GetServer(); int err = s.ExclusiveLock(m_nFirm, m_nLogicNumber, m_dwConnection); if (err == NOERR) m_bExclusiveLock = TRUE; return err; } int TSqlFile::ExclusiveUnlock() { TPrassiServer& s = GetServer(); int err = s.ExclusiveUnlock(m_nFirm, m_nLogicNumber, m_dwConnection); if (err == NOERR) m_bExclusiveLock = FALSE; return err; } TSqlFile::TSqlFile(int nFirm, int nLogicNumber, LPCSTR sWhere, DWORD dwConnection) : m_nLogicNumber(nLogicNumber), m_nFirm(nFirm), m_strWhere(sWhere), m_dwConnection(dwConnection), m_nKey(0), m_dwSnapHandle(0), m_nStatus(_isnotopen), m_nItems(-1) { TPrassiServer& s = GetServer(); m_bExists = s.OpenTableDef(nFirm, nLogicNumber); } TSqlFile::~TSqlFile() { if (m_bExists) { Close(); TPrassiServer& s = GetServer(); s.CloseTableDef(m_nFirm, m_nLogicNumber); } } /////////////////////////////////////////////////////////// // TSqlRecord void TSqlRecord::Clear() { m_Fields.RemoveAll(); } int TSqlRecord::Set(SHORT nIndex, const char* val, DWORD dwSize) { CString& strValue = m_Fields[nIndex]; if (dwSize) { LPTSTR buffer = strValue.GetBufferSetLength(dwSize); memcpy(buffer, val, dwSize); strValue.ReleaseBuffer(); } else strValue = val; return NOERR; } CString TSqlRecord::Get(SHORT nIndex) const { CString strValue; m_Fields.Lookup(nIndex, strValue); return strValue; } void TSqlRecord::SetRecord(CdbRecordset& dbRecordset) { CdbFields& dbFields = dbRecordset.Fields; for (SHORT nIndex = dbFields.GetCount()-1; nIndex >= 0; nIndex--) { CString strValue; if (m_Fields.Lookup(nIndex, strValue)) { if (dbFields[nIndex].GetType() == dbLongBinary) { // TODO: Come si scrive un campo binario? ASSERT(0); } else { COleVariant oleVariant; dbRecordset.SetField(nIndex, &oleVariant); } } } } TSqlRecord::TSqlRecord() { } TSqlRecord::~TSqlRecord() { Clear(); }