676 lines
12 KiB
C++
676 lines
12 KiB
C++
#include "stdafx.h"
|
||
#include "adsdef.h"
|
||
#include "dbftools.h"
|
||
#include "io.h"
|
||
|
||
/////////////////////////////////////////////////////////////////
|
||
// CodeBase -- Database classs
|
||
CodeBase::CodeBase()
|
||
{
|
||
m_pDbfTable = NULL;
|
||
read_only = 0;
|
||
}
|
||
|
||
CodeBase::~CodeBase()
|
||
{
|
||
if (m_pDbfTable != NULL)
|
||
{
|
||
if (m_pDbfTable->IsOpen())
|
||
m_pDbfTable->Close();
|
||
delete m_pDbfTable;
|
||
m_pDbfTable = NULL;
|
||
}
|
||
}
|
||
|
||
DbfTable* CodeBase::Open(const TCHAR *szFile)
|
||
{
|
||
// add by gjm 2010/07/09
|
||
CTDbfString _sfile(szFile);
|
||
if (_access(_sfile.toLPCSTR(), 00) != 0) //exist ?
|
||
return NULL;
|
||
if (_access(_sfile.toLPCSTR(), 06) != 0) // read and write ?
|
||
return NULL;
|
||
// end
|
||
|
||
m_pDbfTable = new DbfTable;
|
||
|
||
// sg add 091013,支持只读方式打开
|
||
int nOpenFlag = TG_DBF_USE_SHARED;
|
||
if (read_only == 1)
|
||
nOpenFlag = TG_DBF_USE_READ_ONLY;
|
||
|
||
if (!m_pDbfTable->Open(szFile, nOpenFlag))
|
||
{
|
||
delete m_pDbfTable;
|
||
m_pDbfTable = NULL;
|
||
return NULL;
|
||
}
|
||
|
||
return m_pDbfTable;
|
||
}
|
||
|
||
DbfTable* CodeBase::Create(const TCHAR *szFile, const FieldInfo *pFieldArray,
|
||
int nCount)
|
||
{
|
||
// 1、创建数据库
|
||
CDBFTableDef *pNewTable = new CDBFTableDef;
|
||
|
||
// 创建数据表,并填入表头信息
|
||
if (!pNewTable->CreateTable(szFile))
|
||
{
|
||
delete pNewTable;
|
||
pNewTable = NULL;
|
||
return NULL;
|
||
}
|
||
|
||
// 增加表列信息
|
||
for (int i=0; i<nCount; i++)
|
||
{
|
||
// 表列信息(DBFField:name、type、len、dec)
|
||
FieldInfo field = pFieldArray[i];
|
||
|
||
// 表列信息(field_name、field_type、field_offset、len_info.char_len、
|
||
FIELD_REC fieldRec;
|
||
memset(&fieldRec, 0, sizeof(FIELD_REC));
|
||
|
||
int nLen = field.m_strName.GetLength();
|
||
|
||
#if (ADS < 17)
|
||
strncpy(fieldRec.field_name, field.m_strName.toLPCSTR(), nLen);
|
||
#else
|
||
strncpy(fieldRec.field_name, field.m_strName.toLPCSTR(), nLen);
|
||
#endif
|
||
fieldRec.field_name[nLen] = EOS; // field_name
|
||
|
||
#if (ADS < 17)
|
||
fieldRec.field_type = field.m_chType; // field_type
|
||
#else
|
||
fieldRec.field_type = field.m_chType; // field_type
|
||
#endif
|
||
|
||
switch(field.m_chType)
|
||
{
|
||
case FLD_TYPE_NUMERIC: // int、double
|
||
fieldRec.len_info.num_size.len = field.m_nLen;
|
||
fieldRec.len_info.num_size.dec = field.m_nDec;
|
||
break;
|
||
case FLD_TYPE_CHARACTER: // string
|
||
case FLD_TYPE_DATE: // date
|
||
case FLD_TYPE_LOGICAL: // bool
|
||
fieldRec.len_info.char_len = field.m_nLen;
|
||
break;
|
||
default:
|
||
break;
|
||
}
|
||
|
||
pNewTable->AddField(&fieldRec);
|
||
}
|
||
|
||
// 更新数据表
|
||
pNewTable->UpdateTable();
|
||
|
||
// 2、关闭数据库
|
||
pNewTable->Close();
|
||
delete pNewTable;
|
||
pNewTable = NULL;
|
||
|
||
// 3、打开
|
||
return Open(szFile);
|
||
}
|
||
|
||
|
||
|
||
/////////////////////////////////////////////////////////////////
|
||
// DbfTable -- Recordset class
|
||
int DbfTable::GetFieldNum()
|
||
{
|
||
int nNum = GetFieldCount();
|
||
return nNum;
|
||
}
|
||
|
||
FieldInfo* DbfTable::GetFieldInfo()
|
||
{
|
||
FieldInfo *pFields = NULL;
|
||
|
||
int nCount = GetFieldNum();
|
||
pFields = new FieldInfo[nCount];
|
||
for (int i=0; i<nCount; i++)
|
||
{
|
||
pFields[i] = (FieldInfo&)m_DBFFields[i];
|
||
}
|
||
return pFields;
|
||
}
|
||
|
||
FieldContent* DbfTable::GetFieldContent(int n)
|
||
{
|
||
FieldContent *pContent = (FieldContent*)m_DBFFields.GetFieldRec(n);
|
||
if (pContent != NULL)
|
||
{
|
||
CTDbfString csContent;
|
||
GetFieldValue(n, csContent);
|
||
|
||
*pContent = (const TCHAR*)(csContent.toCString()); // 赋值
|
||
return pContent;
|
||
}
|
||
return NULL;
|
||
}
|
||
|
||
FieldContent* DbfTable::GetFieldContent(const TCHAR *szFieldName)
|
||
{
|
||
CString csName = szFieldName;
|
||
csName.MakeUpper(); // 全部转化为大写字母
|
||
|
||
int nCount = GetFieldNum();
|
||
for (int i=0; i<nCount; i++)
|
||
{
|
||
DBFField field = m_DBFFields[i];
|
||
|
||
CString csTmp = field.m_strName.toCString();
|
||
csTmp.MakeUpper(); // 全部转化为大写字母
|
||
|
||
if (_tcscmp(csTmp, csName) == 0) // 查找指定列名的列
|
||
{
|
||
FieldContent *pContent = (FieldContent*)m_DBFFields.GetFieldRec(i);
|
||
if (pContent != NULL)
|
||
{
|
||
CTDbfString csContent;
|
||
GetFieldValue(i, csContent);
|
||
|
||
*pContent = (const TCHAR*)(csContent.toCString()); // 赋值
|
||
return pContent;
|
||
}
|
||
return NULL;
|
||
}
|
||
}
|
||
return NULL;
|
||
}
|
||
|
||
long DbfTable::GetRecordCount(int bSkipDeleted)
|
||
{
|
||
if (!bSkipDeleted) // 计算全部记录,包括被删除记录
|
||
return CDBFRecordset::GetRecordCount();
|
||
|
||
long lCount = 0; // 只计算有效记录
|
||
for (MoveFirst(); !IsEOF(); MoveNext())
|
||
lCount ++;
|
||
return lCount;
|
||
}
|
||
|
||
long DbfTable::GetPosition()
|
||
{
|
||
long lPosition = GetAbsolutePosition();
|
||
return lPosition;
|
||
}
|
||
|
||
int DbfTable::IsEOF()
|
||
{
|
||
BOOL bRet = CDBFRecordset::IsEOF();
|
||
return bRet;
|
||
}
|
||
|
||
int DbfTable::IsBOF()
|
||
{
|
||
BOOL bRet = CDBFRecordset::IsBOF();
|
||
return bRet;
|
||
}
|
||
|
||
int DbfTable::IsDeleted()
|
||
{
|
||
BOOL bRet = CDBFRecordset::IsDeleted();
|
||
return bRet;
|
||
}
|
||
|
||
void DbfTable::AppendBegin()
|
||
{
|
||
CDBFRecordset::AddNew();
|
||
m_bIsAdd = true;
|
||
}
|
||
|
||
void DbfTable::AppendEnd()
|
||
{
|
||
CDBFRecordset::Update();
|
||
m_bIsAdd = false;
|
||
}
|
||
|
||
void DbfTable::Close()
|
||
{
|
||
CDBFRecordset::Close();
|
||
}
|
||
|
||
void DbfTable::Delete()
|
||
{
|
||
CDBFRecordset::Delete();
|
||
}
|
||
|
||
BOOL DbfTable::Pack()
|
||
{
|
||
CDBFRecordset::Edit();
|
||
CDBFRecordset::Update();
|
||
return TRUE;
|
||
}
|
||
|
||
int DbfTable::MoveFirst(int bSkipDeleted)
|
||
{
|
||
int nRet = 1;
|
||
CDBFRecordset::MoveFirst();
|
||
if (IsDeleted() && bSkipDeleted)
|
||
nRet = MoveNext(bSkipDeleted);
|
||
return nRet;
|
||
}
|
||
|
||
int DbfTable::MoveLast(int bSkipDeleted)
|
||
{
|
||
int nRet = 1;
|
||
CDBFRecordset::MoveFirst();
|
||
if (IsDeleted() && bSkipDeleted)
|
||
nRet = MovePrev(bSkipDeleted);
|
||
return nRet;
|
||
}
|
||
|
||
int DbfTable::MoveNext(int bSkipDeleted)
|
||
{
|
||
while (1)
|
||
{
|
||
CDBFRecordset::MoveNext();
|
||
if (IsEOF() || !bSkipDeleted)
|
||
break;
|
||
if (!IsDeleted())
|
||
break;
|
||
}
|
||
return (!IsEOF());
|
||
}
|
||
|
||
int DbfTable::MovePrev(int bSkipDeleted)
|
||
{
|
||
while(1)
|
||
{
|
||
CDBFRecordset::MovePrev();
|
||
if (IsBOF() || !bSkipDeleted)
|
||
break;
|
||
if (!IsDeleted())
|
||
break;
|
||
}
|
||
return (!IsBOF());
|
||
}
|
||
|
||
void DbfTable::Move(long offset, int bSkipDeleted)
|
||
{
|
||
if (offset)
|
||
{
|
||
long nStep = offset/abs(offset);
|
||
if (IsBOF() && offset>0)
|
||
{
|
||
MoveFirst(bSkipDeleted);
|
||
offset--;
|
||
}
|
||
|
||
if (IsEOF() && offset<0)
|
||
{
|
||
MoveLast(bSkipDeleted);
|
||
offset++;
|
||
}
|
||
|
||
for (long i=offset; i!=0L; i-=nStep)
|
||
{
|
||
if (nStep > 0)
|
||
MoveNext(bSkipDeleted);
|
||
else
|
||
MovePrev(bSkipDeleted);
|
||
}
|
||
}
|
||
}
|
||
|
||
int DbfTable::MoveTo(long nRecNo)
|
||
{
|
||
CDBFRecordset::Move(nRecNo);
|
||
return 1;
|
||
}
|
||
|
||
int DbfTable::MoveTo(const TCHAR *szKey, const TCHAR *szValue, int nMethod,
|
||
int bSkipDeleted)
|
||
{
|
||
for (MoveFirst(bSkipDeleted); !IsEOF(); MoveNext(bSkipDeleted))
|
||
{
|
||
CString sValue;
|
||
GET_FIELD(this, szKey, sValue);
|
||
|
||
int bEqual = 0;
|
||
if (nMethod == CMP_SENSITIVE)
|
||
bEqual = (_tcscmp(szValue, sValue)==0);
|
||
else
|
||
bEqual = (_tcsicmp(szValue, sValue)==0);
|
||
if (bEqual)
|
||
return 1;
|
||
}
|
||
return 0;
|
||
}
|
||
|
||
int DbfTable::MoveFirst(const TCHAR *szKey, const TCHAR *szValue, int nMethod,
|
||
int bSkipDeleted)
|
||
{
|
||
return MoveTo(szKey, szValue, nMethod, bSkipDeleted);
|
||
}
|
||
|
||
int DbfTable::MoveNext(const TCHAR *szKey, const TCHAR *szValue, int nMethod,
|
||
int bSkipDeleted)
|
||
{
|
||
for (MoveNext(bSkipDeleted); !IsEOF(); MoveNext(bSkipDeleted))
|
||
{
|
||
CString sValue;
|
||
GET_FIELD(this, szKey, sValue);
|
||
|
||
int bEqual = 0;
|
||
if (nMethod == CMP_SENSITIVE)
|
||
bEqual = (_tcscmp(szValue, sValue)==0);
|
||
else
|
||
bEqual = (_tcsicmp(szValue, sValue)==0);
|
||
if (bEqual)
|
||
return 1;
|
||
}
|
||
return 0;
|
||
}
|
||
|
||
void DbfTable::EditMode()
|
||
{
|
||
if (!m_bIsAdd)
|
||
Edit();
|
||
}
|
||
|
||
void DbfTable::EditUpdate()
|
||
{
|
||
if (!m_bIsAdd)
|
||
Update();
|
||
}
|
||
/////////////////////////////////////////////////////////////////
|
||
// FieldInfo -- Field Class
|
||
FieldInfo::FieldInfo(const TCHAR *n, int t, int l, int d)
|
||
{
|
||
InitClear();
|
||
m_strName = n;
|
||
m_chType = t;
|
||
m_nLen = l;
|
||
m_nDec = d;
|
||
}
|
||
|
||
FieldInfo & FieldInfo::operator = (const FieldInfo &src)
|
||
{
|
||
m_strName = src.m_strName;
|
||
m_chType = src.m_chType;
|
||
m_nLen = src.m_nLen;
|
||
m_nDec = src.m_nDec;
|
||
return *this;
|
||
}
|
||
|
||
void FieldInfo::InitClear()
|
||
{
|
||
m_strName = _T("");
|
||
m_chType = _T('\0');
|
||
m_nLen = 0;
|
||
m_nDec = 0;
|
||
}
|
||
|
||
void FieldInfo::ReleaseArray(FieldInfo *p)
|
||
{
|
||
if (p != NULL)
|
||
{
|
||
delete p;
|
||
p = NULL;
|
||
}
|
||
}
|
||
|
||
|
||
|
||
///////////////////////////////////////////////
|
||
// FieldContent -- FieldContent Class
|
||
CString FieldContent::csValue = _T("");
|
||
|
||
TCHAR FieldContent::GetFieldType() const
|
||
{
|
||
return field_type;
|
||
}
|
||
|
||
int FieldContent::CompareTo(const FieldContent &otherOne) const
|
||
{
|
||
if (GetFieldType() != otherOne.GetFieldType())
|
||
return 0;
|
||
|
||
TCHAR cType = GetFieldType();
|
||
|
||
if (cType == FLD_TYPE_NUMERIC)
|
||
{
|
||
if (len_info.num_size.dec == _T('0')) // int
|
||
{
|
||
int n1 = *this,
|
||
n2 = otherOne;
|
||
if (n1 > n2)
|
||
return 1;
|
||
else if (n1 < n2)
|
||
return -1;
|
||
else
|
||
return 0;
|
||
}
|
||
else // double
|
||
{
|
||
double n1 = *this,
|
||
n2 = otherOne;
|
||
if (n1 > n2)
|
||
return 1;
|
||
else if (n1 < n2)
|
||
return -1;
|
||
else
|
||
return 0;
|
||
}
|
||
|
||
}
|
||
else if (cType==FLD_TYPE_CHARACTER || cType==FLD_TYPE_DATE || cType==FLD_TYPE_LOGICAL) // string、date、bool
|
||
{
|
||
const TCHAR *s1 = *this,
|
||
*s2 = otherOne;
|
||
return _tcscmp(s1, s2);
|
||
}
|
||
return 0;
|
||
}
|
||
|
||
FieldContent::operator int () const
|
||
{
|
||
return _ttoi(csValue);
|
||
}
|
||
|
||
FieldContent::operator double () const
|
||
{
|
||
#if ADS == 15
|
||
return atof(csValue);
|
||
#else
|
||
return _tstof(csValue);
|
||
#endif
|
||
}
|
||
|
||
FieldContent::operator float () const
|
||
{
|
||
#if ADS == 15
|
||
double dValue = atof(csValue);
|
||
#else
|
||
double dValue = _tstof(csValue);
|
||
#endif
|
||
return (float)dValue;
|
||
}
|
||
|
||
FieldContent::operator const TCHAR * () const
|
||
{
|
||
return (const TCHAR *)csValue;
|
||
}
|
||
|
||
FieldContent & FieldContent::operator = (int i)
|
||
{
|
||
csValue.Format(_T("%d"), i);
|
||
return *this;
|
||
}
|
||
|
||
FieldContent & FieldContent::operator = (double d)
|
||
{
|
||
csValue.Format(_T("%f"), d);
|
||
return *this;
|
||
}
|
||
|
||
FieldContent & FieldContent::operator = (const TCHAR *str)
|
||
{
|
||
csValue = str;
|
||
return *this;
|
||
}
|
||
|
||
#ifdef __AFXDISP_H__
|
||
// 能正确转换的类型: int, double, string, date
|
||
COleVariant FieldContent::AsVariant() const
|
||
{
|
||
COleVariant res;
|
||
|
||
TCHAR cType = GetFieldType();
|
||
|
||
if (cType == FLD_TYPE_NUMERIC) // int、double
|
||
{
|
||
if (len_info.num_size.dec == _T('0')) // int
|
||
{
|
||
res = (long)_ttoi(csValue);
|
||
}
|
||
else // double
|
||
{
|
||
#if ADS == 15
|
||
res = atof(csValue);
|
||
#else
|
||
res = _tstof(csValue);
|
||
#endif
|
||
|
||
}
|
||
}
|
||
else if (cType == FLD_TYPE_CHARACTER) // string
|
||
{
|
||
const TCHAR *s1 = *this;
|
||
res = s1;
|
||
}
|
||
else if (cType == FLD_TYPE_LOGICAL) // int
|
||
{
|
||
res = (long)_ttoi(csValue);
|
||
}
|
||
return res;
|
||
}
|
||
|
||
FieldContent & FieldContent::operator = (const COleVariant &src)
|
||
{
|
||
int nOleType = V_VT(&src);
|
||
switch(nOleType)
|
||
{
|
||
case VT_BSTR:
|
||
{
|
||
CString cs = V_BSTR(&src);
|
||
const TCHAR *sz = cs;
|
||
*this = sz;
|
||
}
|
||
break;
|
||
case VT_DATE:
|
||
{
|
||
COleDateTime oleDate = V_DATE(&src);
|
||
int nYear = oleDate.GetYear(),
|
||
nMonth = oleDate.GetMonth(),
|
||
nDay = oleDate.GetDay();
|
||
long nDate = nYear*10000 + nMonth*100 + nDay;
|
||
|
||
CString sDate;
|
||
sDate.Format(_T("%ld"), nDate);
|
||
*this = (const TCHAR *)sDate;
|
||
}
|
||
break;
|
||
case VT_I4:
|
||
{
|
||
long n1 = V_I4(&src);
|
||
*this = (int)n1;
|
||
}
|
||
break;
|
||
case VT_I2:
|
||
{
|
||
short n1 = V_I2(&src);
|
||
*this = (int)n1;
|
||
}
|
||
break;
|
||
case VT_R8:
|
||
{
|
||
double n1 = V_R8(&src);
|
||
*this = n1;
|
||
}
|
||
break;
|
||
case VT_R4:
|
||
{
|
||
float n1 = V_R4(&src);
|
||
*this = (double)n1;
|
||
}
|
||
break;
|
||
}
|
||
return *this;
|
||
}
|
||
|
||
template <class K>
|
||
inline int Compare(K n1, K n2)
|
||
{
|
||
if(n1>n2) return 1;
|
||
else if(n1<n2) return -1;
|
||
else return 0;
|
||
}
|
||
|
||
int TDBFUTILITY_IMPEXP CompareVariant(const COleVariant &var1, const COleVariant &var2)
|
||
{
|
||
int nType1 = V_VT(&var1),
|
||
nType2 = V_VT(&var2);
|
||
|
||
int nRes = 0;
|
||
if (nType1 == nType2)
|
||
{
|
||
if (nType1 == VT_BSTR)
|
||
{
|
||
CString s1 = V_BSTR(&var1);
|
||
CString s2 = V_BSTR(&var2);
|
||
nRes = _tcscmp(s1, s2);
|
||
}
|
||
else if (nType1 == VT_DATE)
|
||
{
|
||
double d1 = V_DATE(&var1),
|
||
d2 = V_DATE(&var2);
|
||
int nD1 = (int)d1,
|
||
nD2 = (int)d2;
|
||
nRes = Compare(nD1, nD2);
|
||
}
|
||
else if (nType1 == VT_I4)
|
||
{
|
||
long n1 = V_I4(&var1),
|
||
n2 = V_I4(&var2);
|
||
nRes = Compare(n1, n2);
|
||
}
|
||
else if (nType1 == VT_I2)
|
||
{
|
||
short n1 = V_I2(&var1),
|
||
n2 = V_I2(&var2);
|
||
nRes = Compare(n1, n2);
|
||
}
|
||
else if (nType1 == VT_R8)
|
||
{
|
||
double n1 = V_R8(&var1),
|
||
n2 = V_R8(&var2);
|
||
nRes = Compare(n1, n2);
|
||
}
|
||
else if (nType1 == VT_R4)
|
||
{
|
||
float n1 = V_R4(&var1),
|
||
n2 = V_R4(&var2);
|
||
nRes = Compare(n1, n2);
|
||
}
|
||
}
|
||
return nRes;
|
||
}
|
||
|
||
// 比较两行的大小
|
||
int TDBFUTILITY_IMPEXP CompareBookmark(COleVariant *g_lstSortFieldContents,
|
||
const long *bookmark1, const long *bookmark2)
|
||
{
|
||
COleVariant &var1 = g_lstSortFieldContents[(int)(*bookmark1)],
|
||
&var2 = g_lstSortFieldContents[(int)(*bookmark2)];
|
||
return CompareVariant(var1, var2);
|
||
}
|
||
#endif |