(prima si avevano problemi con le app. autonumeranti) git-svn-id: svn://10.65.10.50/trunk@4922 c028cbd2-c16b-5b4b-a496-9718f37d4682
319 lines
7.3 KiB
C++
Executable File
319 lines
7.3 KiB
C++
Executable File
#include <multirec.h>
|
|
|
|
void TMultiple_rectype::set_body_key(TRectype & rowrec)
|
|
{
|
|
const RecDes* recd = rowrec.rec_des(); // Descrizione del record della testata
|
|
const KeyDes& kd = recd->Ky[0]; // Elenco dei campi della chiave 1
|
|
|
|
// Copia tutti i campi chiave, tranne l'ultimo, in tutti i records
|
|
for (int i = kd.NkFields-2; i >= 0; i--)
|
|
{
|
|
const int nf = kd.FieldSeq[i] % MaxFields;
|
|
const RecFieldDes& rf = recd->Fd[nf];
|
|
const TString& val = get(rf.Name);
|
|
rowrec.renum_key(rf.Name, val);
|
|
}
|
|
}
|
|
|
|
void TMultiple_rectype::load_rows_file(int logicnum)
|
|
{
|
|
const int index = log2ind(logicnum);
|
|
TRectype * rec = new_body_record(logicnum);
|
|
set_body_key(*rec);
|
|
if (_files.objptr(index) == NULL)
|
|
{
|
|
// crea
|
|
TRecord_array * r = new TRecord_array(logicnum, (TString &) _numfields[index]);
|
|
_files.add( r, index);
|
|
}
|
|
((TRecord_array &)_files[index]).read(rec); // rilegge
|
|
_changed[index]=FALSE;
|
|
}
|
|
|
|
int TMultiple_rectype::find(int logicnum, const char * fieldname, const char * s, int from, bool reverse) const
|
|
{
|
|
const TRecord_array & recarray = body(logicnum);
|
|
const int last = recarray.last_row();
|
|
const int len = s ? strlen(s) : 0;
|
|
|
|
if (reverse)
|
|
{
|
|
if (from > 0)
|
|
{
|
|
if (len == 0)
|
|
return from - 1;
|
|
for (int i = recarray.pred_row(from); i > 0; i = recarray.pred_row(i))
|
|
if (recarray[i].get(fieldname) == s)
|
|
return i;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (last > from)
|
|
{
|
|
if (len == 0)
|
|
return from + 1;
|
|
for (int i = recarray.succ_row(from); i <= last; i = recarray.succ_row(i))
|
|
if (recarray[i].get(fieldname) == s)
|
|
return i;
|
|
}
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
int TMultiple_rectype::write_rewrite(TBaseisamfile & f, bool re) const
|
|
{
|
|
int err = NOERR;
|
|
|
|
if (_nuovo && re) // E' nuovo di zecca! quindi ...
|
|
re = FALSE; // ... non fare la rewrite
|
|
|
|
if (re)
|
|
{
|
|
for (int i = _nfiles - 1; err == NOERR && i >= 0 ; i--)
|
|
{
|
|
TRecord_array * r = (TRecord_array *) _files.objptr(i);
|
|
if (r && !_changed[i])
|
|
err = r->write(re);
|
|
}
|
|
// rewrite:
|
|
if (err == NOERR)
|
|
{
|
|
err = TRectype::rewrite(f);
|
|
if (err != NOERR)
|
|
err = TRectype::write(f);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// write:
|
|
((TMultiple_rectype *)this)->renum_key();
|
|
if (_nuovo)
|
|
{
|
|
do
|
|
{
|
|
err = TRectype::write(f);
|
|
if (err == _isreinsert && ((TMultiple_rectype *)this)->renum())
|
|
((TMultiple_rectype *)this)->renum_key();
|
|
} while (err == _isreinsert);
|
|
((TMultiple_rectype *)this)->_nuovo = (err != NOERR);
|
|
}
|
|
else
|
|
{
|
|
err = TRectype::write(f);
|
|
if (err != NOERR)
|
|
err = TRectype::rewrite(f);
|
|
}
|
|
for (int i = _nfiles - 1; err == NOERR && i >= 0 ; i--)
|
|
{
|
|
TRecord_array * r = (TRecord_array *)_files.objptr(i);
|
|
if (r && !_changed[i])
|
|
err = r->write(re);
|
|
}
|
|
}
|
|
return err;
|
|
}
|
|
|
|
void TMultiple_rectype::remove_body(int logicnum)
|
|
{
|
|
const int index = log2ind(logicnum);
|
|
|
|
if (_files.objptr(index) != NULL)
|
|
_files.remove(index);
|
|
}
|
|
|
|
int TMultiple_rectype::log2ind(int logicnum) const
|
|
{
|
|
if (logicnum == 0)
|
|
return 0;
|
|
for (int i = _nfiles - 1; i >= 0 ; i--)
|
|
if (_logicnums[i] == logicnum)
|
|
return i;
|
|
NFCHECK("Can't find file %d in multiple record", logicnum);
|
|
return 0;
|
|
}
|
|
|
|
TRecord_array & TMultiple_rectype::body(int logicnum) const
|
|
{
|
|
const int index = log2ind(logicnum);
|
|
|
|
if (_files.objptr(index) == NULL || _changed[index])
|
|
((TMultiple_rectype *) this)->load_rows_file(_logicnums[index]);
|
|
return (TRecord_array &) _files[index];
|
|
}
|
|
|
|
void TMultiple_rectype::renum_key()
|
|
{
|
|
for (int i = _nfiles - 1; i >= 0 ; i--)
|
|
{
|
|
const int logicnum = _logicnums[i];
|
|
TRecord_array * b = (TRecord_array *) _files.objptr(i);
|
|
if (b)
|
|
{
|
|
TRectype * rec = new TRectype(b->key());
|
|
|
|
set_body_key(*rec);
|
|
b->set_key(rec); // Aggiorna righe
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
TRectype & TMultiple_rectype::operator =(const TRectype & r)
|
|
{
|
|
TRectype::operator=(r);
|
|
reset_fields(*this);
|
|
set_fields(*this);
|
|
return *this;
|
|
}
|
|
|
|
TRectype & TMultiple_rectype::operator =(const char * r)
|
|
{
|
|
TRectype::operator=(r);
|
|
reset_fields(*this);
|
|
set_fields(*this);
|
|
return *this;
|
|
}
|
|
|
|
void TMultiple_rectype::zero(char c)
|
|
{
|
|
reset_fields(*this);
|
|
TAuto_variable_rectype::zero(c);
|
|
for (int i = _nfiles - 1; i >= 0 ; i--)
|
|
if (_files.objptr(i) != NULL)
|
|
((TRecord_array &)_files[i]).destroy_rows();
|
|
}
|
|
|
|
|
|
int TMultiple_rectype::read(TBaseisamfile & f, word op, word lockop)
|
|
{
|
|
int err = NOERR;
|
|
|
|
_nuovo = FALSE;
|
|
if (op == _isequal)
|
|
{
|
|
TRectype r(*this);
|
|
|
|
err = TRectype::read(f, op, lockop);
|
|
if (err != NOERR)
|
|
{
|
|
*this = r;
|
|
_nuovo = TRUE;
|
|
}
|
|
}
|
|
else
|
|
err = TRectype::read(f, op, lockop);
|
|
for (int i = _nfiles - 1; i >= 0 ; i--)
|
|
{
|
|
if (_nuovo)
|
|
{
|
|
TRecord_array * b = (TRecord_array *) _files.objptr(i);
|
|
if (b != NULL)
|
|
{
|
|
_changed[i] = FALSE;
|
|
b->destroy_rows();
|
|
TRectype * r = new_body_record(_logicnums[i]);
|
|
set_body_key(*r);
|
|
b->set_key(r);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (_autoload[i])
|
|
load_rows_file(_logicnums[i]);
|
|
else
|
|
if (_files.objptr(i) != NULL)
|
|
_changed[i] = TRUE;
|
|
}
|
|
}
|
|
return err;
|
|
}
|
|
|
|
int TMultiple_rectype::remove(TBaseisamfile & f) const
|
|
{
|
|
int err = NOERR;
|
|
|
|
for (int i = _nfiles - 1; err == NOERR && i >= 0 ; i--)
|
|
{
|
|
TRecord_array & r = body(_logicnums[i]);
|
|
err = r.remove();
|
|
}
|
|
if (err == NOERR)
|
|
err = TRectype::remove(f);
|
|
return err;
|
|
}
|
|
|
|
// @doc INTERNAL
|
|
TMultiple_rectype::TMultiple_rectype(int hfn)
|
|
: TAuto_variable_rectype(hfn), _nuovo(TRUE), _nfiles(0)
|
|
{
|
|
}
|
|
|
|
void TMultiple_rectype::enable_autoload(int logicnum,bool on)
|
|
{
|
|
const int index = log2ind(logicnum);
|
|
_autoload[index] = on;
|
|
}
|
|
|
|
TRectype & TMultiple_rectype::insert_row(int row, int logicnum)
|
|
{
|
|
TRectype * r = new_body_record(logicnum);
|
|
TRecord_array & b = body(logicnum);
|
|
const int index = log2ind(logicnum);
|
|
|
|
set_body_key(*r);
|
|
r->put(_numfields.row(index), row);
|
|
b.insert_row(r);
|
|
return *r;
|
|
}
|
|
|
|
TRectype & TMultiple_rectype::new_row(int logicnum)
|
|
{
|
|
TRecord_array & b = body(logicnum);
|
|
TRectype & r = b.row(-1, TRUE);
|
|
|
|
return r;
|
|
}
|
|
|
|
bool TMultiple_rectype::autoload_enabled(int logicnum)
|
|
{
|
|
return _autoload[log2ind(logicnum)];
|
|
}
|
|
|
|
// @cmember Aggiunge il corpo lgicnum
|
|
void TMultiple_rectype::add_file(int logicnum, const char * numfield)
|
|
{
|
|
CHECK(_nfiles < maxfiles, "Too many files added");
|
|
_logicnums[_nfiles] = logicnum;
|
|
_autoload[_nfiles] = FALSE;
|
|
_numfields.add(numfield, _nfiles++);
|
|
}
|
|
|
|
TMultiple_rectype::TMultiple_rectype(const TBaseisamfile* file)
|
|
:TAuto_variable_rectype(file), _nuovo(TRUE), _nfiles(0)
|
|
{
|
|
}
|
|
|
|
// @ cmember costruttore dal record
|
|
TMultiple_rectype::TMultiple_rectype(const TRectype & rec)
|
|
:TAuto_variable_rectype(rec), _nuovo(TRUE), _nfiles(0)
|
|
{
|
|
}
|
|
|
|
// @mfunc costruttore di copia
|
|
TMultiple_rectype::TMultiple_rectype(const TMultiple_rectype& r)
|
|
:TAuto_variable_rectype(r), _files(r._files)
|
|
{
|
|
// copia..
|
|
_nuovo=r._nuovo;
|
|
_nfiles=r._nfiles; // file delle righe
|
|
for (int i = _nfiles - 1; i >= 0; i--)
|
|
{
|
|
_logicnums[i] = r._logicnums[i];
|
|
_changed[i] = r._changed[i];
|
|
_autoload[i] = r._autoload[i];
|
|
}
|
|
_numfields=r._numfields;
|
|
}
|
|
|