mirror of
https://github.com/ultimatepp/ultimatepp.git
synced 2026-05-15 22:02:49 -06:00
863 lines
23 KiB
C++
863 lines
23 KiB
C++
#include "dbase.h"
|
|
|
|
dbDatabase::dbDatabase() {
|
|
|
|
numOfTables = 0;
|
|
fhandle = -1;
|
|
opened = false;
|
|
return;
|
|
}
|
|
|
|
dbDatabase::~dbDatabase() {
|
|
Close();
|
|
return;
|
|
}
|
|
|
|
int dbDatabase::Open(const String &dbname) {
|
|
FindFile tb;
|
|
int i;
|
|
unsigned int head;
|
|
unsigned int offset;
|
|
|
|
if(opened == true) return MDTB_DB_OPEN;
|
|
head = 0;
|
|
fileName = dbname;
|
|
|
|
fsize = GetFileLength(fileName);
|
|
#ifdef _WITH_DEBUG
|
|
RLOG("dbDatabase::Open():fsize=" + FormatInt(fsize));
|
|
#endif
|
|
if((fhandle = open(fileName, _O_RDWR|_O_BINARY)) >= 0) {
|
|
lseek(fhandle, 0, 0);
|
|
read(fhandle, &head, 2);
|
|
if(head != MTDB_DB_TYPE) {
|
|
close(fhandle);
|
|
return MTDB_DB_TYPE_ERROR; // il db aperto non e' compatibile
|
|
}
|
|
lseek(fhandle, 16, 0);
|
|
read(fhandle, &numOfTables, 4);
|
|
read(fhandle, &eodsp, 4);
|
|
read(fhandle, &creationTime, sizeof(Time));
|
|
read(fhandle, &lastModifyTime, sizeof(Time));
|
|
|
|
offset = MTDB_DB_HEAD;
|
|
for(i=0; i<numOfTables; i++) {
|
|
struct tableStruct ts;
|
|
ts.offset = offset;
|
|
tables.Add("", ts);
|
|
|
|
tbOpen(i);
|
|
offset += tables[i].tableHead + (tables[i].numOfRecord * tables[i].recordLenght);
|
|
}
|
|
opened = true;
|
|
return fhandle;
|
|
}
|
|
else return -2;
|
|
}
|
|
|
|
void dbDatabase::Close() {
|
|
if(opened == true) {
|
|
tables.Clear();
|
|
fields.Clear();
|
|
numOfTables = 0;
|
|
close(fhandle);
|
|
opened = false;
|
|
}
|
|
return;
|
|
}
|
|
|
|
int dbDatabase::tbOpen(unsigned int handle) {
|
|
int i, p;
|
|
|
|
tables[handle].numOfRecord = 0;
|
|
tables[handle].tableHead = 0;
|
|
tables[handle].recordLenght = 0;
|
|
tables[handle].numOfFields = 0;
|
|
tables[handle].record = 0;
|
|
tables[handle].autoincCntr = 0;
|
|
|
|
lseek(fhandle, tables[handle].offset, 0);
|
|
read(fhandle, &tables[handle].creationTime, 8);
|
|
lseek(fhandle, tables[handle].offset+9, 0);
|
|
read(fhandle, &tables[handle].numOfRecord, 4);
|
|
read(fhandle, &tables[handle].tableHead, 2);
|
|
read(fhandle, &tables[handle].recordLenght, 2);
|
|
read(fhandle, &tables[handle].autoincCntr, 4);
|
|
read(fhandle, &tables[handle].lastModifyTime, 8);
|
|
lseek(fhandle, tables[handle].offset+MTDB_TB_NAME_PTR, 0);
|
|
String::Buffer n(MTDB_TB_NAME_LEN);
|
|
read(fhandle, n, MTDB_TB_NAME_LEN);
|
|
tables[handle].name = n;
|
|
if((p = tables[handle].name.Find('\0')) >= 0) tables[handle].name.Trim(p);
|
|
String::Buffer l(MTDB_TB_COMMENT_LEN);
|
|
lseek(fhandle, tables[handle].offset+MTDB_TB_COMMENT_PTR, 0);
|
|
read(fhandle, l, MTDB_TB_COMMENT_LEN);
|
|
tables[handle].title = l;
|
|
if((p = tables[handle].title.Find('\0')) >= 0) tables[handle].title.Trim(p);
|
|
|
|
tables[handle].numOfFields = ((tables[handle].tableHead-(MTDB_TB_INFO_LEN+1)) / MTDB_TB_FD_LEN);
|
|
ArrayMap<String, struct fieldStruct> field;
|
|
if(tables[handle].numOfFields > 0) {
|
|
unsigned int prevLength = 0;
|
|
for(i=0; i<tables[handle].numOfFields; i++) {
|
|
struct fieldStruct fs;
|
|
fs.length = 0;
|
|
fs.format = 0;
|
|
fs.flags = 0;
|
|
lseek(fhandle, tables[handle].offset+MTDB_TB_INFO_LEN+(MTDB_TB_FD_LEN*i), 0);
|
|
String::Buffer n(MTDB_TB_FD_LABEL_LEN);
|
|
read(fhandle, n, MTDB_TB_FD_LABEL_LEN);
|
|
fs.name = n;
|
|
if((p = fs.name.Find('\0')) >= 0) fs.name.Trim(p);
|
|
read(fhandle, &fs.format, 1);
|
|
fs.format = fs.format << 8;
|
|
read(fhandle, &fs.length, 1);
|
|
read(fhandle, &fs.format, 1);
|
|
read(fhandle, &fs.flags, 1);
|
|
read(fhandle, &fs.nDecimals, 1);
|
|
String::Buffer l(MTDB_TB_COMMENT_LEN);
|
|
lseek(fhandle, tables[handle].offset+MTDB_TB_INFO_LEN+(MTDB_TB_FD_LEN*i)+64, 0);
|
|
read(fhandle, l, MTDB_TB_FLD_CMT_LEN);
|
|
fs.title = l;
|
|
if((p = fs.title.Find('\0')) >= 0) fs.title.Trim(p);
|
|
fs.prevLength = prevLength;
|
|
prevLength += fs.length;
|
|
field.Add(fs.name, fs);
|
|
}
|
|
}
|
|
tables.SetKey(handle, tables[handle].name);
|
|
|
|
int j;
|
|
if((j = fields.Find(tables[handle].name)) >= 0)
|
|
fields[j] = field;
|
|
else
|
|
fields.Add(tables[handle].name, field);
|
|
|
|
return MTDB_SUCCESS;
|
|
}
|
|
|
|
void dbDatabase::dbUpdateHead() {
|
|
|
|
lseek(fhandle, 16, 0);
|
|
write(fhandle, &numOfTables, 4);
|
|
write(fhandle, &eodsp, 4);
|
|
lseek(fhandle, 32, 0);
|
|
Time t = GetSysTime();
|
|
write(fhandle, &t, 8);
|
|
lastModifyTime = t;
|
|
return;
|
|
}
|
|
|
|
int dbDatabase::GetTableHandle(const String &tbname) {
|
|
unsigned int i;
|
|
|
|
for(i=0; i<numOfTables; i++) {
|
|
if(tables[i].name == tbname) {
|
|
return i;
|
|
}
|
|
}
|
|
return MTDB_TB_NOT_FOUND; // table not found
|
|
}
|
|
|
|
bool dbDatabase::IsTable(const String &tbname) {
|
|
unsigned int i;
|
|
|
|
for(i=0; i<numOfTables; i++) {
|
|
if(tables[i].name == tbname) {
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
int dbDatabase::tbPack(unsigned int h) {
|
|
unsigned int i;
|
|
unsigned int pointer;
|
|
|
|
for(i=1; i<=tables[h].numOfRecord; i++) {
|
|
if(IsDeleted(h, i)) {
|
|
pointer = tables[h].offset + tables[h].tableHead + ((i-1) * tables[h].recordLenght);
|
|
Remove(pointer, tables[h].recordLenght);
|
|
eodsp -= tables[h].recordLenght;
|
|
tables[h].numOfRecord--;
|
|
i--;
|
|
}
|
|
}
|
|
dbUpdateHead();
|
|
tbUpdateHead(h);
|
|
ReOpen();
|
|
return MTDB_SUCCESS;
|
|
}
|
|
|
|
int dbDatabase::CopyTableStructure(const String &tbname, const String &dbdest, const String &tbdest) {
|
|
// if dbdest is empty, the copy is in the same database
|
|
dbDatabase dbDest;
|
|
unsigned int h, i, i1, i2, n;
|
|
char buff[512];
|
|
int handle;
|
|
unsigned int eofPtr;
|
|
|
|
if((h = GetTableHandle(tbname)) == MTDB_TB_NOT_FOUND)
|
|
return MTDB_TB_NOT_FOUND;
|
|
|
|
// copy structure
|
|
struct tableStruct newStru = tables[h];
|
|
newStru.numOfRecord = 0;
|
|
newStru.autoincCntr = 0;
|
|
newStru.name = tbdest;
|
|
|
|
if(dbdest.GetLength() > 0) {
|
|
// bisognerebbe controllare che non sia aperto
|
|
handle = dbDest.Open(dbdest);
|
|
eofPtr = dbDest.GetEodsp();
|
|
dbDest.Insert(eofPtr, MTDB_TB_INFO_LEN+(MTDB_TB_FD_LEN*newStru.numOfFields)+1);
|
|
dbDest.SetEodsp(dbDest.GetEodsp() + (MTDB_TB_INFO_LEN+(MTDB_TB_FD_LEN*newStru.numOfFields)+1));
|
|
dbDest.dbUpdateHead();
|
|
n = dbDest.GetCount();
|
|
}
|
|
else {
|
|
handle = fhandle;
|
|
eofPtr = eodsp;
|
|
Insert(eofPtr, MTDB_TB_INFO_LEN+(MTDB_TB_FD_LEN*newStru.numOfFields)+1);
|
|
eodsp += (MTDB_TB_INFO_LEN+(MTDB_TB_FD_LEN*newStru.numOfFields)+1);
|
|
dbUpdateHead();
|
|
n = numOfTables;
|
|
}
|
|
|
|
newStru.offset = eofPtr;
|
|
for(i=0; i<MTDB_TB_INFO_LEN; i++) buff[i] = 0;
|
|
lseek(handle, newStru.offset+0, 0);
|
|
write(handle, buff, MTDB_TB_INFO_LEN);
|
|
|
|
Time t = GetSysTime();
|
|
lseek(handle, newStru.offset, 0);
|
|
write(handle, &t, 8);
|
|
newStru.creationTime = t;
|
|
lseek(handle, newStru.offset+9, 0);
|
|
write(handle, &newStru.numOfRecord, 4);
|
|
write(handle, &newStru.tableHead, 2);
|
|
write(handle, &newStru.recordLenght, 2);
|
|
write(handle, &newStru.autoincCntr, 4);
|
|
write(handle, &t, 8);
|
|
newStru.lastModifyTime = t;
|
|
lseek(handle, newStru.offset+MTDB_TB_NAME_PTR, 0);
|
|
write(handle, newStru.name, newStru.name.GetLength());
|
|
lseek(handle, newStru.offset+MTDB_TB_COMMENT_PTR, 0);
|
|
write(handle, newStru.title, newStru.title.GetLength());
|
|
lseek(handle, newStru.offset+MTDB_TB_INFO_LEN, 0);
|
|
|
|
ArrayMap<String, struct fieldStruct> &fm = fields[h];
|
|
for(i1=0; i1<newStru.numOfFields; i1++) {
|
|
strcpy(buff, fm[i1].name);
|
|
for(i2=MTDB_TB_FD_LABEL_LEN+1; i2<MTDB_TB_FD_LEN; i2++) buff[i2] = 0;
|
|
buff[MTDB_TB_FD_LABEL_LEN+0] = (char)(fm[i1].format >> 8);
|
|
buff[MTDB_TB_FD_LABEL_LEN+1] = (char)(fm[i1].length);
|
|
buff[MTDB_TB_FD_LABEL_LEN+2] = (char)(fm[i1].format);
|
|
buff[MTDB_TB_FD_LABEL_LEN+3] = fm[i1].flags;
|
|
buff[MTDB_TB_FD_LABEL_LEN+4] = (char)fm[i1].nDecimals;
|
|
strcpy(&buff[64], fm[i1].title);
|
|
write(handle, buff, MTDB_TB_FD_LEN);
|
|
}
|
|
i = n + 1;
|
|
lseek(handle, 16, 0);
|
|
write(handle, &i, 4);
|
|
if(dbdest.GetLength() > 0) {
|
|
dbDest.Close();
|
|
}
|
|
else {
|
|
ReOpen();
|
|
}
|
|
return MTDB_SUCCESS;
|
|
}
|
|
|
|
int dbDatabase::AddNewTable(const String &tbname, const String &comment, unsigned int numOfField) {
|
|
int h, i;
|
|
|
|
if(strlen((char*)~tbname) < 1) return MTDB_TB_NAME_ERROR;
|
|
|
|
if((h = GetTableHandle(tbname)) == MTDB_TB_NOT_FOUND) {
|
|
struct tableStruct ntb;
|
|
ntb.name = tbname;
|
|
ntb.title = comment;
|
|
tables.Add(tbname, ntb);
|
|
ArrayMap<String, struct fieldStruct> fs;
|
|
for(i=0; i<numOfField; i++) {
|
|
struct fieldStruct fd;
|
|
fs.Add("", fd);
|
|
}
|
|
fields.Add(tbname, fs);
|
|
h = numOfTables;
|
|
numOfTables++;
|
|
tables[h].offset = 0;
|
|
tables[h].numOfFields = numOfField;
|
|
return MTDB_SUCCESS;
|
|
}
|
|
else return MTDB_TB_EXIST;
|
|
}
|
|
|
|
void dbDatabase::SetTitle(const String &tbname, const String &title) {
|
|
int h;
|
|
|
|
if((h = GetTableHandle(tbname)) >= 0) {
|
|
tables[h].title = title;
|
|
}
|
|
}
|
|
|
|
int dbDatabase::MakeField(const String &tbname, const String &field, const String &comment, unsigned int format, unsigned int length, char flags, unsigned char nDecimals) {
|
|
int h, i;
|
|
|
|
if((h = GetTableHandle(tbname)) == MTDB_TB_NOT_FOUND)
|
|
return MTDB_TB_NOT_FOUND;
|
|
|
|
ArrayMap<String, struct fieldStruct>& fs = fields[h];
|
|
struct fieldStruct *fd;
|
|
for(i=0; i<tables[h].numOfFields; i++) {
|
|
fd = &fs[i];
|
|
if(fd->name.GetLength() > 0) {
|
|
if(fd->name == field) {
|
|
break;
|
|
}
|
|
}
|
|
else {
|
|
break;
|
|
}
|
|
}
|
|
if(i < tables[h].numOfFields) {
|
|
fd->name = field;
|
|
fd->title = comment;
|
|
fd->format = format;
|
|
fd->length = length;
|
|
fd->flags = flags;
|
|
fd->nDecimals = nDecimals;
|
|
return MTDB_SUCCESS;
|
|
}
|
|
return MTDB_TB_ERROR;
|
|
}
|
|
|
|
int dbDatabase::AddField(const String &tbname, const String &field, const String &comment, unsigned int format, unsigned int length, char flags, unsigned char nDecimals) {
|
|
int h;
|
|
|
|
if((h = GetTableHandle(tbname)) == MTDB_TB_NOT_FOUND)
|
|
return MTDB_TB_NOT_FOUND;
|
|
|
|
struct fieldStruct fd;
|
|
fd.name = field;
|
|
fd.title = comment;
|
|
fd.format = format;
|
|
fd.length = length;
|
|
fd.flags = flags;
|
|
fd.nDecimals = nDecimals;
|
|
ArrayMap<String, struct fieldStruct> &fs = fields[h];
|
|
fs.Add(field, fd);
|
|
tables[h].numOfFields++;
|
|
return MTDB_SUCCESS;
|
|
}
|
|
|
|
int dbDatabase::SetField(const String &tbname, unsigned int column, const String &field, const String &comment, unsigned int format, unsigned int length, char flags, unsigned char nDecimals) {
|
|
int h, i;
|
|
|
|
if((h = GetTableHandle(tbname)) == MTDB_TB_NOT_FOUND)
|
|
return MTDB_TB_NOT_FOUND;
|
|
|
|
i = column;
|
|
if(i < tables[h].numOfFields) {
|
|
ArrayMap<String, struct fieldStruct> &fs = fields[h];
|
|
fs[i].name = field;
|
|
fs[i].title = comment;
|
|
fs[i].format = format;
|
|
fs[i].length = length;
|
|
fs[i].flags = flags;
|
|
fs[i].nDecimals = nDecimals;
|
|
//fs.SetKey(i, field);
|
|
return MTDB_SUCCESS;
|
|
}
|
|
return MTDB_TB_ERROR;
|
|
}
|
|
|
|
int dbDatabase::RemoveField(const String &tbname, const String &field) {
|
|
int h, i;
|
|
|
|
if((h = GetTableHandle(tbname)) == MTDB_TB_NOT_FOUND)
|
|
return MTDB_TB_NOT_FOUND;
|
|
|
|
ArrayMap<String, struct fieldStruct>& fs = fields[h];
|
|
for(i=0; i<tables[h].numOfFields; i++) {
|
|
if(fs.GetKey(i) == field) {
|
|
fs.Remove(i);
|
|
tables[h].numOfFields--;
|
|
return MTDB_SUCCESS;
|
|
}
|
|
}
|
|
return MTDB_TB_ERROR;
|
|
}
|
|
|
|
bool dbDatabase::IsField(const String &tbname, const String &field) {
|
|
int h, i;
|
|
|
|
if((h = GetTableHandle(tbname)) == MTDB_TB_NOT_FOUND)
|
|
return false;
|
|
|
|
ArrayMap<String, struct fieldStruct>& fs = fields[h];
|
|
for(i=0; i<tables[h].numOfFields; i++) {
|
|
if(fs.GetKey(i) == field) {
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
int dbDatabase::MakeTable(const String &tbname) {
|
|
char buff[512];
|
|
unsigned int i1, i2, i3, h;
|
|
|
|
if((h = GetTableHandle(tbname)) == MTDB_TB_NOT_FOUND)
|
|
return MTDB_TB_NOT_FOUND;
|
|
|
|
tables[h].numOfRecord = 0;
|
|
tables[h].autoincCntr = 0;
|
|
Time t = GetSysTime();
|
|
tables[h].creationTime = t;
|
|
tables[h].lastModifyTime = t;
|
|
i3 = 0;
|
|
ArrayMap<String, struct fieldStruct> &fs = fields[h];
|
|
for(i1=0; i1<tables[h].numOfFields; i1++) {
|
|
if(fs[i1].format == MTDB_STR) {
|
|
i3 += fs[i1].length;
|
|
}
|
|
else if(fs[i1].format == MTDB_INT) {
|
|
i3 += 4;
|
|
fs[i1].length = 4;
|
|
}
|
|
else if(fs[i1].format == MTDB_DOUBLE) {
|
|
i3 += 8;
|
|
fs[i1].length = 8;
|
|
}
|
|
else if(fs[i1].format == MTDB_BOOL) {
|
|
i3 += 1;
|
|
fs[i1].length = 1;
|
|
}
|
|
else if(fs[i1].format == MTDB_DATETIME || fs[i1].format == MTDB_DATE || fs[i1].format == MTDB_TIME) {
|
|
//i3 += sizeof(int);
|
|
//fs[i1].length = sizeof(time_t);
|
|
i3 += sizeof(Time);
|
|
fs[i1].length = sizeof(Time);
|
|
}
|
|
else if(fs[i1].format >= 0x0100 && fs[i1].format <= 0x02ff) {
|
|
i3 += 4;
|
|
fs[i1].length = 4;
|
|
}
|
|
}
|
|
i3++; // aggiungo 1 byte per l'informazione su record cancellato o no.
|
|
tables[h].tableHead = MTDB_TB_INFO_LEN+1+(tables[h].numOfFields*MTDB_TB_FD_LEN);
|
|
tables[h].recordLenght = i3;
|
|
if(tables[h].offset == 0) {
|
|
tables[h].offset = eodsp;
|
|
Insert(eodsp, MTDB_TB_INFO_LEN+(MTDB_TB_FD_LEN*tables[h].numOfFields)+1);
|
|
eodsp += (MTDB_TB_INFO_LEN+(MTDB_TB_FD_LEN*tables[h].numOfFields)+1);
|
|
}
|
|
else {
|
|
eodsp = tables[h].offset + (MTDB_TB_INFO_LEN+(MTDB_TB_FD_LEN*tables[h].numOfFields)+1);
|
|
}
|
|
tbUpdateHead(h);
|
|
for(i1=0; i1<tables[h].numOfFields; i1++) {
|
|
strcpy(buff, fs[i1].name);
|
|
for(i2=MTDB_TB_FD_LABEL_LEN+1; i2<MTDB_TB_FD_LEN; i2++) buff[i2] = 0;
|
|
buff[MTDB_TB_FD_LABEL_LEN+0] = (char)(fs[i1].format >> 8);
|
|
buff[MTDB_TB_FD_LABEL_LEN+1] = (char)(fs[i1].length);
|
|
buff[MTDB_TB_FD_LABEL_LEN+2] = (char)(fs[i1].format);
|
|
buff[MTDB_TB_FD_LABEL_LEN+3] = fs[i1].flags;
|
|
buff[MTDB_TB_FD_LABEL_LEN+4] = (char)fs[i1].nDecimals;
|
|
strcpy(&buff[64], fs[i1].title);
|
|
write(fhandle, buff, MTDB_TB_FD_LEN);
|
|
}
|
|
dbUpdateHead();
|
|
ReOpen();
|
|
return MTDB_SUCCESS;
|
|
}
|
|
|
|
int dbDatabase::TableZap(const String &tbname) {
|
|
int i;
|
|
|
|
for(i=1; i<=GetNumOfRec(tbname); i++) {
|
|
DelRec(tbname, i);
|
|
}
|
|
tbPack(GetTableHandle(tbname));
|
|
return MTDB_SUCCESS;
|
|
}
|
|
|
|
int dbDatabase::tbUpdateHead(unsigned int h) {
|
|
unsigned int head;
|
|
char buff[512];
|
|
int i;
|
|
|
|
for(i=0; i<MTDB_TB_INFO_LEN; i++) buff[i] = 0;
|
|
lseek(fhandle, tables[h].offset+0, 0);
|
|
write(fhandle, buff, MTDB_TB_INFO_LEN);
|
|
|
|
lseek(fhandle, tables[h].offset, 0);
|
|
write(fhandle, &tables[h].creationTime, 8);
|
|
lseek(fhandle, tables[h].offset+9, 0);
|
|
write(fhandle, &tables[h].numOfRecord, 4);
|
|
write(fhandle, &tables[h].tableHead, 2);
|
|
write(fhandle, &tables[h].recordLenght, 2);
|
|
write(fhandle, &tables[h].autoincCntr, 4);
|
|
Time t = GetSysTime();
|
|
write(fhandle, &t, 8);
|
|
tables[h].lastModifyTime = t;
|
|
lseek(fhandle, tables[h].offset+MTDB_TB_NAME_PTR, 0);
|
|
write(fhandle, tables[h].name, MTDB_TB_NAME_LEN);
|
|
lseek(fhandle, tables[h].offset+MTDB_TB_COMMENT_PTR, 0);
|
|
write(fhandle, tables[h].title, MTDB_TB_COMMENT_LEN);
|
|
lseek(fhandle, tables[h].offset+MTDB_TB_INFO_LEN, 0);
|
|
return MTDB_SUCCESS;
|
|
}
|
|
|
|
int dbDatabase::DeleteTable(const String &tbname) {
|
|
int h;
|
|
|
|
if((h = GetTableHandle(tbname)) == MTDB_TB_NOT_FOUND)
|
|
return MTDB_TB_NOT_FOUND;
|
|
|
|
return DeleteTable(h);
|
|
}
|
|
|
|
int dbDatabase::DeleteTable(int tbHandle) {
|
|
unsigned int length, r;
|
|
|
|
if(tbHandle+1 < numOfTables) {
|
|
length = tables[tbHandle+1].offset - tables[tbHandle].offset;
|
|
}
|
|
else {
|
|
length = eodsp - tables[tbHandle].offset;
|
|
}
|
|
Remove(tables[tbHandle].offset, length);
|
|
eodsp -= length;
|
|
numOfTables--;
|
|
dbUpdateHead();
|
|
ReOpen();
|
|
return MTDB_SUCCESS;
|
|
}
|
|
|
|
int dbDatabase::AlterTable(const String &tbname) {
|
|
unsigned int length, r, h, i;
|
|
|
|
if((h = GetTableHandle(tbname)) == MTDB_TB_NOT_FOUND)
|
|
return MTDB_TB_NOT_FOUND;
|
|
|
|
struct tableStruct new_table_stru = tables[h];
|
|
ArrayMap<String, struct fieldStruct> new_fields_stru = fields[h];
|
|
tbOpen(h); // reload old structure for correct query
|
|
dbRecordSet rs1;
|
|
//carico tutto il contenuto della vecchia tabella
|
|
rs1.Fetch(Query("SELECT * FROM " + tbname));
|
|
//restore new table stru
|
|
Vector<String> oldkey;
|
|
for(int z=0; z<new_fields_stru.GetCount(); z++) {
|
|
oldkey.Add(new_fields_stru.GetKey(z));
|
|
}
|
|
tables[h] = new_table_stru;
|
|
fields[h] = new_fields_stru;
|
|
if(h+1 < numOfTables) {
|
|
length = tables[h+1].offset - tables[h].offset;
|
|
}
|
|
else {
|
|
length = eodsp - tables[h].offset;
|
|
}
|
|
Remove(tables[h].offset, length);
|
|
eodsp -= length;
|
|
tables[h].offset = 0;
|
|
MakeTable(tbname);
|
|
h = numOfTables-1;
|
|
for(int z=0; z<oldkey.GetCount(); z++) {
|
|
fields[h].SetKey(z, oldkey[z]);
|
|
}
|
|
//riscrivo i datinella tabella con la nuova formattazione
|
|
dbRecord rc1;
|
|
for(i=0; i<rs1.GetCount(); i++) {
|
|
rc1 = rs1.Get();
|
|
String query;
|
|
query = "INSERT INTO " + tbname + " (";
|
|
for(int nc=0; nc<rc1.GetCount(); nc++) {
|
|
query.Cat(rc1.GetName(nc));
|
|
query.Cat(",");
|
|
}
|
|
query.Cat(") VALUES (");
|
|
for(int nc=0; nc<rc1.GetCount(); nc++) {
|
|
query.Cat(CSVQuote(AsString(rc1.GetValue(nc))));
|
|
query.Cat(",");
|
|
}
|
|
query.Cat(")");
|
|
#ifdef _WITH_DEBUG
|
|
RLOGHEXDUMP(query, query.GetCount());
|
|
#endif
|
|
Query(query);
|
|
rs1.Next();
|
|
}
|
|
ReOpen();
|
|
return MTDB_SUCCESS;
|
|
}
|
|
|
|
int dbDatabase::DelRec(const String &tbname, int recno) {
|
|
int h;
|
|
|
|
if((h = GetTableHandle(tbname)) == MTDB_TB_NOT_FOUND)
|
|
return MTDB_TB_NOT_FOUND;
|
|
|
|
return DelRec(h, recno);
|
|
}
|
|
|
|
int dbDatabase::DelRec(unsigned int tbHandle, int recno) {
|
|
char buff[1];
|
|
|
|
if(recno == MTDB_TB_APP)
|
|
return MTDB_INV_RECNO;
|
|
else if(recno > tables[tbHandle].numOfRecord)
|
|
return MTDB_INV_RECNO;
|
|
if(recno > 0)
|
|
tables[tbHandle].record = recno;
|
|
else if(recno == MTDB_TB_ACT)
|
|
recno = tables[tbHandle].record;
|
|
else
|
|
return MTDB_TB_NOPOINTER;
|
|
|
|
lseek(fhandle, (int)tables[tbHandle].offset+tables[tbHandle].tableHead+(tables[tbHandle].recordLenght*(recno-1)), 0);
|
|
buff[0] = MTDB_TB_RECORD_DELETED;
|
|
write(fhandle, buff, 1);
|
|
return MTDB_SUCCESS;
|
|
}
|
|
|
|
bool dbDatabase::IsDeleted(unsigned int tbHandle, int recno) {
|
|
char buff[1];
|
|
|
|
if(tables[tbHandle].numOfRecord < recno) return false;
|
|
|
|
lseek(fhandle, (int)tables[tbHandle].offset+tables[tbHandle].tableHead+(tables[tbHandle].recordLenght*(recno-1)), 0);
|
|
read(fhandle, buff, 1);
|
|
if(buff[0] == MTDB_TB_RECORD_DELETED) return true;
|
|
return false;
|
|
}
|
|
|
|
int dbDatabase::MakeDB(const String &dbname) {
|
|
int handle;
|
|
char buff[1024];
|
|
int i;
|
|
|
|
handle = open((char*)~dbname, _O_CREAT|_O_RDWR|_O_BINARY, S_IRUSR | S_IWUSR);
|
|
for(i=0; i<1024; i++) buff[i] = 0;
|
|
unsigned int head;
|
|
unsigned char ver;
|
|
head = MTDB_DB_TYPE;
|
|
ver = MTDB_version_;
|
|
numOfTables = 0;
|
|
eodsp = 1024;
|
|
lseek(handle, 0, 0);
|
|
write(handle, &buff, 1024);
|
|
lseek(handle, 0, 0);
|
|
write(handle, &head, 2);
|
|
write(handle, &ver, 1);
|
|
lseek(handle, 16, 0);
|
|
write(handle, &numOfTables, 4);
|
|
write(handle, &eodsp, 4);
|
|
Time t = GetSysTime();
|
|
write(handle, &t, 8);
|
|
write(handle, &t, 8);
|
|
close(handle);
|
|
|
|
return MTDB_SUCCESS;
|
|
}
|
|
|
|
int dbDatabase::Pack() {
|
|
int i, r;
|
|
|
|
// pack the fixed space tables
|
|
for(i=0; i<numOfTables; i++) {
|
|
r = tbPack(i);
|
|
if(r != MTDB_SUCCESS) return r;
|
|
}
|
|
|
|
// pack the undefined size area
|
|
int newHandle;
|
|
String tempFName;
|
|
char mem1[65536];
|
|
unsigned int l, n;
|
|
unsigned int rest;
|
|
dbDatabase dbx;
|
|
Value v;
|
|
|
|
tempFName = GetFileDirectory(fileName) + "temp.tmp";
|
|
newHandle = open((char*)~tempFName, _O_CREAT|_O_RDWR|_O_BINARY, S_IRUSR | S_IWUSR);
|
|
lseek(fhandle, 0, 0);
|
|
lseek(newHandle, 0, 0);
|
|
l = (eodsp/65536);
|
|
rest = eodsp-(l*65536);
|
|
while(l > 0) {
|
|
read(fhandle, &mem1, 65536);
|
|
write(newHandle, &mem1, 65536);
|
|
l--;
|
|
}
|
|
read(fhandle, &mem1, rest);
|
|
write(newHandle, &mem1, rest);
|
|
close(newHandle);
|
|
dbx.Open(tempFName);
|
|
for(l=0; l<numOfTables; l++) {
|
|
ArrayMap<String, struct fieldStruct> &fs = fields[l];
|
|
for(i=0; i<tables[l].numOfFields; i++) {
|
|
if(fs[i].format >= 0x0100 && fs[i].format <= 0x02ff) {
|
|
for(n=1; n<=tables[l].numOfRecord; n++) {
|
|
if(FieldGet(l, n, i, v) == 0) {
|
|
dbx.FieldPut(l, n, i, v, false, true);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
dbx.Close();
|
|
close(fhandle);
|
|
FileDelete(fileName);
|
|
FileMove((char*)~tempFName, fileName);
|
|
fsize = GetFileLength(fileName);
|
|
fhandle = open(fileName, _O_RDWR|_O_BINARY);
|
|
return MTDB_SUCCESS;
|
|
}
|
|
|
|
int dbDatabase::ReOpen() {
|
|
String buff;
|
|
|
|
buff.Cat(fileName);
|
|
Close();
|
|
return Open(buff);
|
|
}
|
|
|
|
void dbDatabase::Insert(unsigned int start, unsigned int length) {
|
|
int newHandle;
|
|
String tempFName;
|
|
char mem1[65536];
|
|
unsigned int i;
|
|
unsigned int rest;
|
|
|
|
tempFName = GetFileDirectory(fileName) + "~temp.tmp";
|
|
newHandle = open((char*)~tempFName, _O_CREAT|_O_RDWR|_O_BINARY, S_IRUSR | S_IWUSR);
|
|
lseek(fhandle, 0, 0);
|
|
lseek(newHandle, 0, 0);
|
|
|
|
if(start > 0) {
|
|
i = (start/65536);
|
|
rest = start-(i*65536);
|
|
while(i > 0) {
|
|
read(fhandle, &mem1, 65536);
|
|
write(newHandle, &mem1, 65536);
|
|
i--;
|
|
}
|
|
read(fhandle, &mem1, rest);
|
|
write(newHandle, &mem1, rest);
|
|
}
|
|
for(i=0; i<65536; i++) mem1[i] = 0;
|
|
i = (length/65536);
|
|
rest = length-(i*65536);
|
|
while(i > 0) {
|
|
write(newHandle, &mem1, 65536);
|
|
i--;
|
|
}
|
|
write(newHandle, &mem1, rest);
|
|
if(start<=fsize) {
|
|
i=((fsize-start)/65536);
|
|
rest=(fsize-start)-(i*65536);
|
|
while(i > 0) {
|
|
read(fhandle, &mem1, 65536);
|
|
write(newHandle, &mem1, 65536);
|
|
i--;
|
|
}
|
|
read(fhandle, &mem1, rest);
|
|
write(newHandle, &mem1, rest);
|
|
}
|
|
close(fhandle);
|
|
close(newHandle);
|
|
FileDelete(fileName);
|
|
FileMove((char*)~tempFName, fileName);
|
|
fsize = GetFileLength(fileName);
|
|
fhandle = open(fileName, _O_RDWR|_O_BINARY);
|
|
return;
|
|
}
|
|
|
|
void dbDatabase::Remove(unsigned int start, unsigned int length) {
|
|
int newHandle;
|
|
String tempFName;
|
|
char mem1[65536];
|
|
unsigned int i;
|
|
unsigned int rest;
|
|
|
|
tempFName = GetFileDirectory(fileName) + "~temp.tmp";
|
|
newHandle = open((char*)~tempFName, _O_CREAT|_O_RDWR|_O_BINARY, S_IRUSR | S_IWUSR);
|
|
lseek(fhandle, 0, 0);
|
|
lseek(newHandle, 0, 0);
|
|
|
|
if(start > 0) {
|
|
i = (start/65536);
|
|
rest = start - (i * 65536);
|
|
while(i > 0) {
|
|
read(fhandle, &mem1, 65536);
|
|
write(newHandle, &mem1, 65536);
|
|
i--;
|
|
}
|
|
read(fhandle, &mem1, rest);
|
|
write(newHandle, &mem1, rest);
|
|
}
|
|
|
|
lseek(fhandle, start+length, 0);
|
|
|
|
if((start+length) < fsize) {
|
|
i = ((fsize-(start+length))/65536);
|
|
rest = ((fsize-(start+length)) - (i * 65536));
|
|
while(i > 0) {
|
|
read(fhandle, &mem1, 65536);
|
|
write(newHandle, &mem1, 65536);
|
|
i--;
|
|
}
|
|
read(fhandle, &mem1, rest);
|
|
write(newHandle, &mem1, rest);
|
|
}
|
|
close(fhandle);
|
|
close(newHandle);
|
|
FileDelete(fileName);
|
|
FileMove((char*)~tempFName, fileName);
|
|
fsize = GetFileLength(fileName);
|
|
#ifdef _WITH_DEBUG
|
|
RLOG("dbDatabase::Remove():fsize=" + FormatInt(fsize));
|
|
#endif
|
|
fhandle = open(fileName, _O_RDWR|_O_BINARY);
|
|
return;
|
|
}
|
|
|
|
bool dbDatabase::SwapFieldUp(const String &tb, unsigned int field) {
|
|
int h;
|
|
|
|
if((h = GetTableHandle(tb)) == MTDB_TB_NOT_FOUND) return false;
|
|
|
|
if(field > 0 && field <= fields[h].GetCount()) {
|
|
struct fieldStruct field_buff = fields[h][field];
|
|
String key_buff = fields[h].GetKey(field);
|
|
fields[h][field] = fields[h][field-1];
|
|
fields[h][field-1] = field_buff;
|
|
fields[h].SetKey(field, fields[h].GetKey(field-1));
|
|
fields[h].SetKey(field-1, key_buff);
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
bool dbDatabase::SwapFieldDown(const String &tb, unsigned int field) {
|
|
int h;
|
|
|
|
if((h = GetTableHandle(tb)) == MTDB_TB_NOT_FOUND) return false;
|
|
|
|
if(field < (fields[h].GetCount()-1) && field >= 0) {
|
|
struct fieldStruct field_buff = fields[h][field];
|
|
String key_buff = fields[h].GetKey(field);
|
|
fields[h][field] = fields[h][field+1];
|
|
fields[h][field+1] = field_buff;
|
|
fields[h].SetKey(field, fields[h].GetKey(field+1));
|
|
fields[h].SetKey(field+1, key_buff);
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|