//-----------------------------------------------------------------------------+ // Copyright (C), 1998-2007, Beijing Tangent Software Co. Ltd. // = FileName : DbfUtility.cpp // = Version : ver2.0 // = Author : wlw // = CreateDate : 2002-09-09 // = Description: Dbf工具类的定义 // = Maintainers: // //-----------------------------------------------------------------------------+ /* Copyright?2002, Alexey Dolgachov mail: alxsoft@gazinter.net web: http://www.alxsoft.narod.ru */ #include "StdAfx.h" #include "DbfUtility.h" #include "TAString.h" #include "TUString.h" #include "TSqlCondition.h" #include "TSqlQuiry.h" #if ADS>15 #include #else #include #endif FieldInfo::FieldInfo(const TCHAR *n, int t, int l, int d) { InitClear(); if (n) { name = _strdup(_AS(n)); } type = t; len = l; dec = d; } FieldInfo::FieldInfo(const FieldInfo &src) { InitClear(); *this = src; } FieldInfo::~FieldInfo() { if (name) { free(name); } } FieldInfo& FieldInfo::operator= (const FieldInfo &src) { if (name) { free(name); } if (src.name) { name = _strdup(src.name); } else { name = NULL; } type = src.type; len = src.len; dec = src.dec; return *this; } void FieldInfo::InitClear() { name = NULL; type = 0; len = 0; dec = 0; } int FieldInfo::operator !() { return !name; } /////////////////////////////////////////////// // CodeBase -- Database classs CodeBase::CodeBase() { d4init(this); open_error = 0; safety = 0; auto_open = 0; // for auto open index exclusive = 0; read_only = 0; read_lock = 0; lock_attempts = -1; } CodeBase::~CodeBase() { d4close_all(this); d4init_undo(this); } DbfTable * CodeBase::Open(const TCHAR *szFile) { TCHAR szShortPath[256] = _T(""); if (GetShortPathName(szFile, szShortPath, 256) == 0) { return NULL; } return(DbfTable *) d4open(this, _AS(szShortPath)); } DbfTable * CodeBase::Create(const TCHAR *szFile, const FieldInfo *pFieldArray) { return (DbfTable *)d4create(this, (char *)_AS(szFile), (FIELD4INFO *)pFieldArray, NULL); } //////////////////////////////////////////////////////////// // Recordset class DbfTable::DbfTable() { } FieldInfo * DbfTable::GetFieldInfo() { return (FieldInfo *)d4field_info(this); } int DbfTable::GetFieldNum() { return d4num_fields(this); } FieldContent * DbfTable::GetFieldContent(const TCHAR *szFieldName) { return (FieldContent *)d4field(this, (char *)_AS(szFieldName)); } // n=0, 1, 2, ..., base on ZERO FieldContent * DbfTable::GetFieldContent(int n) { return (FieldContent *)d4field_j(this, n+1); } void DbfTable::Close() { d4close(this); } void DbfTable::AppendBegin() { d4append_start(this,0); d4blank(this); } void DbfTable::AppendEnd() { d4append(this); } void DbfTable::Delete() { d4delete(this); } void DbfTable::Recall() { d4recall(this); } BOOL DbfTable::Pack() { return !d4pack(this); } // Iteration int DbfTable::MoveFirst(int bSkipDeleted) { int nRet = (d4top(this) == 0 ? TRUE : FALSE); if (IsDeleted() && bSkipDeleted) { nRet = MoveNext(bSkipDeleted); } return nRet; } int DbfTable::MoveLast(int bSkipDeleted) { int nRet = (d4bottom(this) == 0 ? TRUE : FALSE); if (IsDeleted() && bSkipDeleted) { nRet = MovePrev(bSkipDeleted); } return nRet; } int DbfTable::MoveNext(int bSkipDeleted) { while (1) { d4skip(this, 1L); if (IsEOF() || !bSkipDeleted) { break; } if (!IsDeleted()) { break; } } return (!IsEOF()); } int DbfTable::MovePrev(int bSkipDeleted) { while(1) { d4skip(this, -1L); 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::IsEOF() { return d4eof(this); } int DbfTable::IsBOF() { return d4bof(this); } int DbfTable::MoveTo(long nRecNo) { return (d4go(this, nRecNo + 1) == 0); } // Now, match method is not supported int DbfTable::MoveTo(const TCHAR *szKey, const TCHAR *szValue, int nMethod, int bSkipDeleted) { for (MoveFirst(bSkipDeleted); !IsEOF(); MoveNext(bSkipDeleted)) { TCString 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)) { TCString 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; } long DbfTable::GetPosition() { return d4recno(this)-1; } int DbfTable::IsDeleted() { return d4deleted(this); } BOOL DbfTable::operator !() { return (IsEOF() || IsBOF()); } int FieldContent::CompareTo(const FieldContent &otherOne) const { if (GetFieldType() != otherOne.GetFieldType()) { return 0; } char cType = GetFieldType(); if (cType == r4num) { if (f4decimals((FIELD4 *)this) == 0) { int n1 = *this, n2 = otherOne; if (n1 > n2) { return 1; } else if (n1 < n2) { return -1; } else { return 0; } } else { double n1 = *this, n2 = otherOne; if (n1 > n2) { return 1; } else if (n1 < n2) { return -1; } else { return 0; } } } else if (cType == r4str || cType == r4date || cType == r4log) { const TCHAR * s1 = *this, *s2 = otherOne; return _tcscmp(s1, s2); } return 0; } // 求总记录数 long DbfTable::GetRecordCount(int bSkipDeleted) { if (!bSkipDeleted) { return d4reccount(this); } long lCount = 0; for (MoveFirst(); !IsEOF(); MoveNext()) { lCount ++; } return lCount; } void FieldInfo::ReleaseArray(FieldInfo *p) { u4free(p); } /////////////////////////////////////////////// // FieldContent TCHAR FieldContent::szValue[256] = _T(""); FieldContent::FieldContent() { } FieldContent::operator int () const { return f4int((FIELD4 *)this); } FieldContent::operator double () const { return f4double((FIELD4 *)this); } FieldContent::operator float () const { return (float)f4double((FIELD4 *)this); } FieldContent::operator const TCHAR * () const { #ifdef _UNICODE char buf[256]; TGh1cpy(buf, f4str((FIELD4 *)this)); _tcscpy(szValue,TString(buf)); #else TGh1cpy(szValue, f4str((FIELD4 *)this)); #endif return (const TCHAR *)szValue; } char FieldContent::GetFieldType() const { return f4type((FIELD4 *)this); } FieldContent & FieldContent::operator = (int i) { f4assign_int(this, i); return *this; } FieldContent & FieldContent::operator = (double d) { f4assign_double(this, d); return *this; } FieldContent & FieldContent::operator = (const TCHAR *str) { f4assign(this, (char *)_AS(str)); return *this; } #ifdef __AFXDISP_H__ // 能正确正确转换的类型: int, double, string, date COleVariant FieldContent::AsVariant() const { COleVariant res; char cType=GetFieldType(); if (cType == r4num) { if (f4decimals((FIELD4 *)this) == 0) { res = (long)f4int((FIELD4 *)this); } else { res = f4double((FIELD4 *)this); } } else if (cType == r4str) { const TCHAR* s1 = *this; ASSERT(s1 != NULL); res = s1; } else if (cType == r4log) { res = (long)f4int((FIELD4 *)this); } 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; TCString sDate(_T("%ld"), nDate); *this = 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; } int TARCH_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 TARCH_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 // 修改: 可以改多个记录 // 查询: 仅列出最后一个满足条件的记录 int DBFFUN(DbfAccess &kz) { CodeBase code_base; code_base.exclusive = (kz.flag == FLAG_PACK ? 1 : 0); DATA4 *table = code_base.Open(kz.dbfname); if (table == NULL) { return 1; } if (kz.flag == FLAG_PACK) { d4pack(table); return 0; } FIELD4 *field; int i,len; char buf[150] = "", buf1[150] = ""; FILE *ftext = NULL; int retFlag = 0; int dbflen = d4num_fields(table); // 由字段名换算字段序号 int *keyindex = kz.keynum > 0 ? new int [kz.keynum] : NULL; //如果不指定关键字则查询全部记录 int *dataindex = kz.datanum > 0 ? new int [kz.datanum] : NULL; for (int k = 0; k < kz.keynum; k++) { if ((keyindex[k] = d4field_number(table, kz.keyFieldName[k])) <= 0) { return 1; } } for (k = 0; k < kz.datanum; k++) { if ((dataindex[k] = d4field_number(table, kz.dataFieldName[k])) <= 0) { return 1; } } int isExist = 0; if (kz.flag == FLAG_READ || kz.flag == FLAG_WRITE || kz.flag == FLAG_DELETE) // read or modify { if (kz.flag == FLAG_READ) { if ((ftext = fopen(kz.resFileName,"w")) == NULL) { return 1; } } for (d4top(table); !d4eof(table); d4skip(table, 1L)) { if (d4deleted(table)) { continue; } for (i = 0; i < kz.keynum; i++) { if (keyindex[i] > dbflen) { if (!kz.flag) { fclose(ftext); } return 1; } field = d4field_j(table,keyindex[i]); // 局部比较, 当最后一字符为*时 int iLen = strlen(kz.keyinfo[i]); int locCmp = (iLen >= 1 && kz.keyinfo[i][iLen - 1] == '*'); len = locCmp ? (iLen - 1) : f4len(field); TGh3cpy(buf,kz.keyinfo[i],len); TGh3cpy(buf1,f4str(field),len); if (memcmp(buf,buf1,len)) { break; //本行不满足查询条件 } } if (i == kz.keynum) // Find { isExist = 1; if (kz.flag == FLAG_WRITE) // Write { for (i = 0; i < kz.datanum; i++) { if (dataindex[i] > dbflen) { exit(0); } field = d4field_j(table,dataindex[i]); len = f4len(field); TGh2cpy(buf,kz.dataIn[i],len); if (f4type(field)==r4num && buf[0]) //数值型 { double f = atof(buf); f4assign_double(field,f); } else { f4assign(field,kz.dataIn[i]); } } d4flush(table); d4unlock(table); } else if (kz.flag == FLAG_READ) // Read { for (i = 0; i < kz.datanum; i++) { if (dataindex[i] > dbflen) { fclose(ftext); exit(0); } field = d4field_j(table,dataindex[i]); len = f4len(field); TGh1cpy(buf,f4str(field)); fprintf(ftext,"\"%s\" ",buf); } fprintf(ftext,"\n"); } else if (kz.flag == FLAG_DELETE) { d4delete(table); } } } if (ftext && kz.flag == FLAG_READ) { fclose(ftext); } } if (kz.flag == FLAG_APPEND || (kz.flag == FLAG_WRITE && !isExist)) { d4append_start(table,0); d4blank(table); for (i = 0; i < kz.datanum; i++) { if (dataindex[i] > dbflen) { exit(0); } field = d4field_j(table,dataindex[i]); len = f4len(field); TGh2cpy(buf,kz.dataIn[i],len); if (f4type(field) == r4num && buf[0]) //数值型 { double f = atof(buf); f4assign_double(field,f); } else { f4assign(field,kz.dataIn[i]); } } retFlag = d4append(table); d4flush(table); d4unlock(table); } if (keyindex) { delete keyindex; } if (dataindex) { delete dataindex; } return retFlag; } // keynum >=0 and datanum >0 DbfAccess:: DbfAccess(const TCHAR *tabName, int isWrite, int kn, int dn) : flag(isWrite), keynum(kn), datanum(dn) { _tcscpy(dbfname, tabName); if (keynum < 0 || datanum < 0) { exit(1); } keyFieldName = keynum > 0 ? new char * [keynum] : NULL; keyinfo = keynum > 0 ? new char * [keynum] : NULL; for (int i = 0; i < keynum; i++) { keyFieldName[i] = keyinfo[i] = NULL; } dataFieldName = datanum > 0 ? new char * [datanum] : NULL; for (i = 0; i < datanum; i++) { dataFieldName[i] = NULL; } if (flag == FLAG_WRITE || flag == FLAG_APPEND) // write append { dataIn = new char * [datanum]; for (i = 0; i < datanum; i++) { dataIn[i] = NULL; } } else { dataIn = NULL; resFileName = NULL; } } /******************* DbfAccess *****************/ DbfAccess:: ~DbfAccess() { for (int i = 0; i < keynum; i++) { if (keyFieldName[i]) { free(keyFieldName[i]); } if (keyinfo[i]) { free(keyinfo[i]); } } if (keyFieldName) { delete[] keyFieldName; } if (keyinfo) { delete[] keyinfo; } for (i = 0; i < datanum; i++) { if (dataFieldName[i]) { free(dataFieldName[i]); } if (dataFieldName) { delete[] dataFieldName; } if (flag == FLAG_WRITE || flag == FLAG_APPEND) { for (i = 0; i < datanum; i++) { if (dataIn[i]) { free(dataIn[i]); } } if (dataIn) { delete[] dataIn; } } else if (flag == FLAG_READ) { if (resFileName) { free(resFileName); } } } } unsigned _stklen = 30000U; static int IsDigit(const char *str) { int len = strlen(str); for (int i = 0; i < len; i++) { if (!isdigit(str[i])) { return 0; } } return 1; } int operator == (TCStringList &strs1, TCStringList &strs2) { if (strs1.Length() != strs2.Length()) { return 0; } int len = strs1.Length(); for (int i = 0; i=2 // syntax: SELECT []/<*> FROM [] // := WHERE = // value can't be empty, but can be ''(empty string) int TARCH_IMPEXP SqlExec(const TCHAR *sqlcmd, const TCHAR *quiryOut, TDPtrList *res) { if (!sqlcmd) { return 0; } TSqlQuiry cmd; int i = 1; int from = 0, where = 0; TCString word(256); while (GetStringAtIndex(sqlcmd, i, word)) { if (i==1) { if (_tcsicmp(word, _T("SELECT")) != 0) { return 0; } } else if (!from && _tcsicmp(word, _T("from")) == 0) { from = 1; } else if (!where && _tcsicmp(word, _T("where")) == 0) { where = 1; } else { if (!from) // Specify OutPut field { if (_tcsicmp(word, _T("DISTINCT")) == 0) { cmd.isDistinct = 1; } else { cmd.outputFields.Append(tstrnew(word)); } } else { if (!where && !cmd.dbfFile) { cmd.dbfFile = word; } else if (where) // Condtion is here { const char *pstr; char fieldKey[80] = "", fieldValue[256] = ""; DataCompare cp; TAString aword(word); if ((pstr = strstr(aword, ">="))) { int n = 0; for (const char *p = aword; p != pstr; p++, n++) { fieldKey[n] = *p; } fieldKey[n] = 0; strcpy(fieldValue, p+2); cp = GREAT_EQUAL; } else if ((pstr = strchr(aword, '>'))) { int n = 0; for (const char *p = aword; p != pstr; p++, n++) { fieldKey[n] = *p; } fieldKey[n] = 0; strcpy(fieldValue, p+1); cp = GREAT; } else if ((pstr = strstr(aword, "<="))) { int n = 0; for (const char *p = aword; p != pstr; p++, n++) { fieldKey[n] = *p; } fieldKey[n] = 0; strcpy(fieldValue, p+2); cp = LITTLE_EQUAL; } else if ((pstr = strchr(aword, '<'))) { int n = 0; for (const char *p = aword; p != pstr; p++, n++) { fieldKey[n] = *p; } fieldKey[n] = 0; strcpy(fieldValue, p+1); cp = LITTLE; } else if ((pstr = strstr(aword, "!="))) { int n = 0; for (const char *p = aword; p != pstr; p++, n++) { fieldKey[n] = *p; } fieldKey[n] = 0; strcpy(fieldValue, p+2); cp = NOT_EQUAL; } else if ((pstr = strchr(aword, '='))) { int n = 0; for (const char *p = aword; p != pstr; p++, n++) { fieldKey[n] = *p; } fieldKey[n] = 0; strcpy(fieldValue, p+1); cp = EQUAL; } else { return 0; } if (!fieldKey[0] || !fieldValue[0]) { return 0; } TSqlCondition *condPtr = new TSqlCondition; condPtr->fieldName = fieldKey; condPtr->opr = cp; int nLen = strlen(fieldValue); if (fieldValue[0] == '\'' && nLen > 1 && fieldValue[nLen-1] == '\'') { condPtr->type = SQL_CHAR; char str[256]; strcpy(str, &fieldValue[1]); str[strlen(str) - 1] = 0; condPtr->rstring = _strdup(str); } else if (IsDigit(fieldValue)) { condPtr->type = SQL_INT; condPtr->rint = atoi(fieldValue); } else if (strchr(fieldValue, '.')) { condPtr->type = SQL_REAL; condPtr->rreal= atof(fieldValue); } else { condPtr->type = SQL_CHAR; condPtr->rstring = _strdup(fieldValue); } cmd.conditions.Append(condPtr); } } } i++; } if (cmd.Execute()) { if (quiryOut) { #if (ADS > 15) std:: #endif ofstream fileOut(quiryOut); cmd.QuiryOut(fileOut); } if (res) { res->Reset(); int len = cmd.outbuf.Length(); for (int k = 0; k < len; k++) { TCStringList *strList = new TCStringList; *strList = *cmd.outbuf[k]; res->Append(strList); } } return 1; } else { } return 0; }