campo-sirio/servers/odbc/sqlfile.cpp
guy c4ac448443 Servers
git-svn-id: svn://10.65.10.50/trunk@5855 c028cbd2-c16b-5b4b-a496-9718f37d4682
1998-01-07 10:17:26 +00:00

823 lines
14 KiB
C++
Executable File

#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();
}