campo-sirio/include/multirec.cpp
alex 5bf4cfa86f Patch level : xx.7.054
Files correlati     :
Ricompilazione Demo : [ ]
Commento            :
Riportata la versione 1.7 patch 054 sul main trunk (II)


git-svn-id: svn://10.65.10.50/trunk@9665 c028cbd2-c16b-5b4b-a496-9718f37d4682
2001-05-04 10:59:04 +00:00

433 lines
10 KiB
C++
Executable File
Raw Blame History

#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);
TRecord_array* r = (TRecord_array*)_files.objptr(index);
if (r == NULL)
{
// crea
r = new TRecord_array(logicnum, (TString &) _numfields[index]);
_files.add(r, index);
}
TRectype* rec = new_body_record(logicnum);
set_body_key(*rec);
r->read(rec); // rilegge
_changed.reset(index);
}
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 = _files.last(); err == NOERR && i >= 0 ; i = _files.pred(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 & myself = *(TMultiple_rectype *)this;
const bool to_complete = !myself.key_complete();
if (to_complete)
myself.renum();
myself.renum_key();
myself._nuovo |= to_complete;
if (_nuovo)
{
do
{
err = TRectype::write(f);
if (err == _isreinsert)
if (myself.renum())
myself.renum_key();
else
break;
} while (err == _isreinsert);
myself._nuovo = (err != NOERR);
}
else
{
err = TRectype::write(f);
if (err != NOERR)
err = TRectype::rewrite(f);
}
for (int i = _files.last(); err == NOERR && i >= 0 ; i = _files.pred(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);
_files.destroy(index);
}
int TMultiple_rectype::log2ind(int logicnum) const
{
if (logicnum <= 0)
return 0;
for (int i = _logicnums.last(); i >= 0 ; i--)
if (lognum(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(lognum(index));
return (TRecord_array&) _files[index];
}
void TMultiple_rectype::renum_key()
{
TString oldkey;
for (int i = _files.last(); i >= 0 ; i = _files.pred(i))
{
const int logicnum = lognum(i);
TRecord_array * b = & body(logicnum);
if (b)
{
if (i==0)
oldkey=b->key().build_key();
// convertire al piu' presto le seguenti righe ...
TRectype * rec = new TRectype(b->key());
set_body_key(*rec);
b->set_key(rec); // Aggiorna righe
// .. nella piu' economiche
//set_body_key(*b);
// ...dove set_body_key(TRecarray & b) e' la nuova funzione virtuale da implementare
// che realizza direttamente la rinumerazione del record array
if (i==0)
if (oldkey != b->key().build_key())
_nuovo = TRUE;
}
}
}
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 = _files.last(); i >= 0 ; i = _files.pred(i))
((TRecord_array &)_files[i]).destroy_rows();
_nuovo = TRUE;
}
int TMultiple_rectype::readat(TBaseisamfile& f, TRecnotype nrec, word lockop)
{
_nuovo = FALSE;
int err = TRectype::readat(f, nrec, lockop);
synchronize_bodies();
return err;
}
int TMultiple_rectype::read(TBaseisamfile & f, word op, word lockop)
{
int err = NOERR;
_nuovo = FALSE;
if (op == _isequal)
{
const TRectype oldr(*this);
err = TRectype::read(f, op, lockop);
if (err != NOERR)
{
*this = oldr;
_nuovo = TRUE;
}
}
else
{
err = TRectype::read(f, op, lockop);
}
synchronize_bodies();
return err;
}
void TMultiple_rectype::synchronize_bodies()
{
for (int i = _logicnums.last(); i >= 0 ; i--)
{
if (_nuovo)
{
TRecord_array * b = (TRecord_array *) _files.objptr(i);
if (b == NULL)
{
b = new TRecord_array(lognum(i), (TString &) _numfields[i]);
_files.add(b, i);
}
_changed.reset(i);
b->destroy_rows();
TRectype * r = new_body_record(lognum(i));
set_body_key(*r);
b->set_key(r);
}
else
{
if (_autoload[i])
load_rows_file(lognum(i));
else
if (_files.objptr(i) != NULL)
_changed.set(i);
}
}
}
// @mfunc Copia il multiple rectype r su quello corrente
TMultiple_rectype & TMultiple_rectype::copy(const TMultiple_rectype& r)
{
// copia..
TAuto_variable_rectype::operator=((TAuto_variable_rectype&)r);
_nuovo = r._nuovo;
_files = r._files;
_logicnums = r._logicnums;
_changed = r._changed;
_autoload = r._autoload;
_numfields = r._numfields;
return *this;
}
// @mfunc Copia il multiple rectype r su quello corrente
int TMultiple_rectype::loaded_rows(int logicnum) const
{
const int index = log2ind(logicnum);
TRecord_array* r = (TRecord_array*) ((TMultiple_rectype *) this)->_files.objptr(index);
if (_changed[index] || r == NULL)
return 0;
return r->rows();
}
// @mfunc confronta due record multipli
// Affidabilit<69> 95%
int TMultiple_rectype::compare(const TSortable& s) const
{
int res = TRectype::compare(s);
TMultiple_rectype & m = (TMultiple_rectype &) s;
for (int i = 0 ; res == 0 && i < _logicnums.items(); i++)
{
const int logicnum = lognum(i);
TRecord_array & r = body(logicnum);
TRecord_array & r1 = m.body(logicnum);
res = r.rows() - r1.rows();
if (res == 0 && r.rows() > 0 && r1.rows() > 0)
{
for (int j = r.last_row(), k = r1.last_row(); res == 0 && j > 0 && k > 0; j = r.pred_row(j), k = r1.pred_row(k))
{
res = j - k; // Controlla che non ci siano salti
if (res == 0)
res = r[j].compare(r1[j]);
}
}
}
return res;
}
// @mfunc controlla se due record multipli sono uguali
// Affidabilit<69> 100%
bool TMultiple_rectype::is_equal(const TMultiple_rectype& m) const
{
bool yes = TRectype::is_equal(m);
const int last = _logicnums.last(); // qui
for (int i = 0; yes && i < last; i++)
{
const int logicnum = lognum(i);
TRecord_array & r = body(logicnum);
TRecord_array & r1 = m.body(logicnum);
yes = r.rows() == r1.rows();
if (yes && r.rows() > 0 && r1.rows() > 0)
{
for (int j = r.last_row(), k = r1.last_row(); yes && j > 0 && k > 0; j = r.pred_row(j), k = r1.pred_row(k))
{
yes = (j == k) && r[j].is_equal(r1[k]);
}
}
}
return yes;
}
int TMultiple_rectype::remove(TBaseisamfile & f) const
{
int err = NOERR;
for (int i = _files.last(); err == NOERR && i >= 0 ; i = _files.pred(i))
{
TRecord_array & r = body(lognum(i));
err = r.remove();
}
if (err == NOERR)
err = TRectype::remove(f);
return err;
}
void TMultiple_rectype::fill_transaction(TConfig& cfg, int row) const
{
CHECK(row == 0, "You can't specify a row for multiple rectypes");
TRectype::fill_transaction(cfg);
const int last = _logicnums.last(); // qui
for (int i = 0; i < last; i++)
{
TRecord_array& b = body(lognum(i));
for (int r = 1; b.exist(r); r++)
b[r].fill_transaction(cfg, r);
}
}
// @doc INTERNAL
TMultiple_rectype::TMultiple_rectype(int hfn)
: TAuto_variable_rectype(hfn), _nuovo(TRUE)
{
}
void TMultiple_rectype::enable_autoload(int logicnum,bool on)
{
const int index = log2ind(logicnum);
_autoload.set(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)
{
_logicnums.add_long(logicnum);
_numfields.add(numfield);
}
TMultiple_rectype::TMultiple_rectype(const TBaseisamfile* file)
:TAuto_variable_rectype(file), _nuovo(TRUE)
{
}
// @ cmember costruttore dal record
TMultiple_rectype::TMultiple_rectype(const TRectype & rec)
:TAuto_variable_rectype(rec), _nuovo(TRUE)
{
}
// @mfunc costruttore di copia
TMultiple_rectype::TMultiple_rectype(const TMultiple_rectype& r)
:TAuto_variable_rectype(r)
{
// copia..
copy(r);
}