2005-04-21 11:08:06 +00:00
|
|
|
|
#include <stdlib.h>
|
|
|
|
|
|
1997-06-03 16:06:27 +00:00
|
|
|
|
#include <multirec.h>
|
2005-01-17 15:57:00 +00:00
|
|
|
|
#include <relation.h>
|
|
|
|
|
|
2005-04-05 13:58:30 +00:00
|
|
|
|
bool TMultiple_rectype::key_complete() const
|
2005-01-17 15:57:00 +00:00
|
|
|
|
{
|
2008-12-10 16:52:43 +00:00
|
|
|
|
const RecDes& recd = rec_des(); // Descrizione del record
|
2005-01-17 15:57:00 +00:00
|
|
|
|
const KeyDes& kd = recd.Ky[0];
|
|
|
|
|
const int nf = kd.FieldSeq[kd.NkFields - 1] % MaxFields; //posizione ultimo campo chiave principale
|
|
|
|
|
const RecFieldDes& rf = recd.Fd[nf];
|
|
|
|
|
|
2005-04-21 11:08:06 +00:00
|
|
|
|
const TString& val = get(rf.Name);
|
|
|
|
|
bool ok = !val.blank();
|
|
|
|
|
if (ok)
|
|
|
|
|
{
|
|
|
|
|
const int type = rf.TypeF; // Controllo meglio i campi numerici
|
|
|
|
|
if (type == _intfld || type == _longfld || type == _intzerofld || type == _longzerofld)
|
|
|
|
|
ok = atol(val) > 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return ok;
|
2005-01-17 15:57:00 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//assegna il prossimo numero all'ultimo campo della chiave principale della testata
|
|
|
|
|
bool TMultiple_rectype::renum()
|
|
|
|
|
{
|
2008-12-10 16:52:43 +00:00
|
|
|
|
const RecDes& recd = rec_des(); // Descrizione del record
|
2005-01-17 15:57:00 +00:00
|
|
|
|
const KeyDes& kd = recd.Ky[0];
|
|
|
|
|
const int nf = kd.FieldSeq[kd.NkFields - 1] % MaxFields; //posizione ultimo campo chiave principale
|
|
|
|
|
const RecFieldDes& rf = recd.Fd[nf];
|
2005-04-21 11:08:06 +00:00
|
|
|
|
|
|
|
|
|
const int type = rf.TypeF; // Controllo che il campo sia numerico
|
|
|
|
|
if (type != _intfld && type != _longfld && type != _intzerofld && type != _longzerofld)
|
|
|
|
|
return false;
|
|
|
|
|
|
2005-01-17 15:57:00 +00:00
|
|
|
|
TRectype::zero(rf.Name); //azzera il contenuto del campo chiave numerico
|
|
|
|
|
long next_num = 1;
|
|
|
|
|
|
|
|
|
|
if (kd.NkFields == 1) //chiave principale con un solo campo
|
|
|
|
|
{
|
|
|
|
|
TLocalisamfile file(num());
|
|
|
|
|
if (file.last() == NOERR)
|
|
|
|
|
next_num += file.get_long(rf.Name);
|
|
|
|
|
}
|
|
|
|
|
else //chiave principale con piu' campi
|
|
|
|
|
{
|
|
|
|
|
TRelation rel(num()); //relazione sul file principale
|
|
|
|
|
TCursor cur(&rel, "", 1, this, this); //cursore generale per chiavi multicampo
|
|
|
|
|
const long items = cur.items();
|
|
|
|
|
|
|
|
|
|
if (items > 0)
|
|
|
|
|
{
|
|
|
|
|
cur.freeze();
|
|
|
|
|
cur = items - 1; //va sull'ultimo record del file
|
|
|
|
|
next_num += cur.curr().get_long(rf.Name);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
put(rf.Name, next_num);
|
|
|
|
|
|
2005-04-21 11:08:06 +00:00
|
|
|
|
return true;
|
2005-01-17 15:57:00 +00:00
|
|
|
|
}
|
1997-06-03 16:06:27 +00:00
|
|
|
|
|
1997-06-06 10:32:05 +00:00
|
|
|
|
void TMultiple_rectype::set_body_key(TRectype & rowrec)
|
|
|
|
|
{
|
2008-12-10 16:52:43 +00:00
|
|
|
|
const RecDes& recd = rowrec.rec_des(); // Descrizione del record della testata
|
|
|
|
|
const KeyDes& kd = recd.Ky[0]; // Elenco dei campi della chiave 1
|
1997-06-06 10:32:05 +00:00
|
|
|
|
|
1998-08-10 10:20:31 +00:00
|
|
|
|
// Copia tutti i campi chiave, tranne l'ultimo, in tutti i records
|
1997-06-06 10:32:05 +00:00
|
|
|
|
for (int i = kd.NkFields-2; i >= 0; i--)
|
|
|
|
|
{
|
|
|
|
|
const int nf = kd.FieldSeq[i] % MaxFields;
|
2008-12-10 16:52:43 +00:00
|
|
|
|
const RecFieldDes& rf = recd.Fd[nf];
|
1997-06-06 10:32:05 +00:00
|
|
|
|
const TString& val = get(rf.Name);
|
|
|
|
|
rowrec.renum_key(rf.Name, val);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
1997-06-03 16:06:27 +00:00
|
|
|
|
void TMultiple_rectype::load_rows_file(int logicnum)
|
|
|
|
|
{
|
|
|
|
|
const int index = log2ind(logicnum);
|
1998-08-10 10:20:31 +00:00
|
|
|
|
TRecord_array* r = (TRecord_array*)_files.objptr(index);
|
|
|
|
|
if (r == NULL)
|
1997-06-06 16:37:06 +00:00
|
|
|
|
{
|
1997-06-13 14:00:54 +00:00
|
|
|
|
// crea
|
2005-05-17 15:37:43 +00:00
|
|
|
|
r = new TRecord_array(logicnum, _numfields.row(index));
|
1998-08-10 10:20:31 +00:00
|
|
|
|
_files.add(r, index);
|
1997-06-13 14:00:54 +00:00
|
|
|
|
}
|
1998-08-10 10:20:31 +00:00
|
|
|
|
TRectype* rec = new_body_record(logicnum);
|
|
|
|
|
set_body_key(*rec);
|
|
|
|
|
r->read(rec); // rilegge
|
1998-04-30 15:09:06 +00:00
|
|
|
|
_changed.reset(index);
|
1997-06-03 16:06:27 +00:00
|
|
|
|
}
|
|
|
|
|
|
2003-04-16 15:49:59 +00:00
|
|
|
|
int TMultiple_rectype::find(int logicnum, const char* fieldname, const char* s, int from, bool reverse) const
|
1997-06-03 16:06:27 +00:00
|
|
|
|
{
|
|
|
|
|
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)
|
|
|
|
|
{
|
1998-04-30 15:09:06 +00:00
|
|
|
|
for (int i = _files.last(); err == NOERR && i >= 0 ; i = _files.pred(i))
|
1997-06-03 16:06:27 +00:00
|
|
|
|
{
|
|
|
|
|
TRecord_array * r = (TRecord_array *) _files.objptr(i);
|
1997-06-06 16:37:06 +00:00
|
|
|
|
if (r && !_changed[i])
|
1997-06-03 16:06:27 +00:00
|
|
|
|
err = r->write(re);
|
|
|
|
|
}
|
|
|
|
|
// rewrite:
|
|
|
|
|
if (err == NOERR)
|
|
|
|
|
{
|
|
|
|
|
err = TRectype::rewrite(f);
|
|
|
|
|
if (err != NOERR)
|
|
|
|
|
err = TRectype::write(f);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
// write:
|
1997-08-18 16:03:20 +00:00
|
|
|
|
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;
|
1997-06-03 16:06:27 +00:00
|
|
|
|
if (_nuovo)
|
|
|
|
|
{
|
|
|
|
|
do
|
|
|
|
|
{
|
|
|
|
|
err = TRectype::write(f);
|
1999-04-06 15:34:39 +00:00
|
|
|
|
if (err == _isreinsert)
|
|
|
|
|
if (myself.renum())
|
|
|
|
|
myself.renum_key();
|
|
|
|
|
else
|
|
|
|
|
break;
|
1997-06-06 10:32:05 +00:00
|
|
|
|
} while (err == _isreinsert);
|
1997-08-18 16:03:20 +00:00
|
|
|
|
myself._nuovo = (err != NOERR);
|
1997-06-03 16:06:27 +00:00
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
err = TRectype::write(f);
|
|
|
|
|
if (err != NOERR)
|
|
|
|
|
err = TRectype::rewrite(f);
|
|
|
|
|
}
|
1998-04-30 15:09:06 +00:00
|
|
|
|
for (int i = _files.last(); err == NOERR && i >= 0 ; i = _files.pred(i))
|
1997-06-03 16:06:27 +00:00
|
|
|
|
{
|
|
|
|
|
TRecord_array * r = (TRecord_array *)_files.objptr(i);
|
1997-06-06 16:37:06 +00:00
|
|
|
|
if (r && !_changed[i])
|
1997-06-03 16:06:27 +00:00
|
|
|
|
err = r->write(re);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return err;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void TMultiple_rectype::remove_body(int logicnum)
|
|
|
|
|
{
|
|
|
|
|
const int index = log2ind(logicnum);
|
1998-11-03 10:27:35 +00:00
|
|
|
|
_files.destroy(index);
|
1997-06-03 16:06:27 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int TMultiple_rectype::log2ind(int logicnum) const
|
|
|
|
|
{
|
1998-04-30 15:09:06 +00:00
|
|
|
|
if (logicnum <= 0)
|
1997-06-03 16:06:27 +00:00
|
|
|
|
return 0;
|
1998-04-30 15:09:06 +00:00
|
|
|
|
for (int i = _logicnums.last(); i >= 0 ; i--)
|
|
|
|
|
if (lognum(i) == logicnum)
|
1997-06-03 16:06:27 +00:00
|
|
|
|
return i;
|
|
|
|
|
NFCHECK("Can't find file %d in multiple record", logicnum);
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
1998-04-30 15:09:06 +00:00
|
|
|
|
TRecord_array& TMultiple_rectype::body(int logicnum) const
|
1997-06-03 16:06:27 +00:00
|
|
|
|
{
|
|
|
|
|
const int index = log2ind(logicnum);
|
|
|
|
|
|
1998-04-30 15:09:06 +00:00
|
|
|
|
if (_files.objptr(index) == NULL || _changed[index])
|
|
|
|
|
((TMultiple_rectype*) this)->load_rows_file(lognum(index));
|
|
|
|
|
return (TRecord_array&) _files[index];
|
1997-06-03 16:06:27 +00:00
|
|
|
|
}
|
|
|
|
|
|
1997-06-06 10:32:05 +00:00
|
|
|
|
void TMultiple_rectype::renum_key()
|
1997-06-03 16:06:27 +00:00
|
|
|
|
{
|
1999-04-06 15:34:39 +00:00
|
|
|
|
TString oldkey;
|
1998-04-30 15:09:06 +00:00
|
|
|
|
for (int i = _files.last(); i >= 0 ; i = _files.pred(i))
|
1997-06-06 10:32:05 +00:00
|
|
|
|
{
|
1999-04-06 15:34:39 +00:00
|
|
|
|
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;
|
|
|
|
|
}
|
1997-06-06 10:32:05 +00:00
|
|
|
|
}
|
1997-06-03 16:06:27 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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);
|
1998-04-30 15:09:06 +00:00
|
|
|
|
for (int i = _files.last(); i >= 0 ; i = _files.pred(i))
|
|
|
|
|
((TRecord_array &)_files[i]).destroy_rows();
|
1999-04-06 15:34:39 +00:00
|
|
|
|
_nuovo = TRUE;
|
1997-06-03 16:06:27 +00:00
|
|
|
|
}
|
|
|
|
|
|
1997-07-28 09:41:46 +00:00
|
|
|
|
int TMultiple_rectype::readat(TBaseisamfile& f, TRecnotype nrec, word lockop)
|
|
|
|
|
{
|
|
|
|
|
_nuovo = FALSE;
|
1998-04-30 15:09:06 +00:00
|
|
|
|
int err = TRectype::readat(f, nrec, lockop);
|
1997-07-28 09:41:46 +00:00
|
|
|
|
synchronize_bodies();
|
|
|
|
|
return err;
|
|
|
|
|
}
|
1997-06-03 16:06:27 +00:00
|
|
|
|
|
1997-06-27 09:13:03 +00:00
|
|
|
|
int TMultiple_rectype::read(TBaseisamfile & f, word op, word lockop)
|
1997-06-03 16:06:27 +00:00
|
|
|
|
{
|
1997-06-13 14:00:54 +00:00
|
|
|
|
int err = NOERR;
|
1997-06-03 16:06:27 +00:00
|
|
|
|
|
1997-06-13 14:00:54 +00:00
|
|
|
|
_nuovo = FALSE;
|
|
|
|
|
if (op == _isequal)
|
|
|
|
|
{
|
1998-08-10 10:20:31 +00:00
|
|
|
|
const TRectype oldr(*this);
|
1997-06-13 14:00:54 +00:00
|
|
|
|
|
|
|
|
|
err = TRectype::read(f, op, lockop);
|
|
|
|
|
if (err != NOERR)
|
|
|
|
|
{
|
1998-08-10 10:20:31 +00:00
|
|
|
|
*this = oldr;
|
1997-06-13 14:00:54 +00:00
|
|
|
|
_nuovo = TRUE;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
1998-08-10 10:20:31 +00:00
|
|
|
|
{
|
1997-06-13 14:00:54 +00:00
|
|
|
|
err = TRectype::read(f, op, lockop);
|
1998-08-10 10:20:31 +00:00
|
|
|
|
}
|
|
|
|
|
|
1997-07-28 09:41:46 +00:00
|
|
|
|
synchronize_bodies();
|
1998-08-10 10:20:31 +00:00
|
|
|
|
|
1997-07-28 09:41:46 +00:00
|
|
|
|
return err;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void TMultiple_rectype::synchronize_bodies()
|
|
|
|
|
{
|
1998-04-30 15:09:06 +00:00
|
|
|
|
for (int i = _logicnums.last(); i >= 0 ; i--)
|
1997-06-06 16:37:06 +00:00
|
|
|
|
{
|
1997-06-13 14:00:54 +00:00
|
|
|
|
if (_nuovo)
|
|
|
|
|
{
|
|
|
|
|
TRecord_array * b = (TRecord_array *) _files.objptr(i);
|
2001-04-30 15:04:10 +00:00
|
|
|
|
if (b == NULL)
|
1997-06-13 14:00:54 +00:00
|
|
|
|
{
|
2001-05-04 10:59:04 +00:00
|
|
|
|
b = new TRecord_array(lognum(i), (TString &) _numfields[i]);
|
2001-04-30 15:04:10 +00:00
|
|
|
|
_files.add(b, i);
|
1997-06-13 14:00:54 +00:00
|
|
|
|
}
|
2001-05-04 10:59:04 +00:00
|
|
|
|
_changed.reset(i);
|
2001-04-30 15:04:10 +00:00
|
|
|
|
b->destroy_rows();
|
2001-05-04 10:59:04 +00:00
|
|
|
|
TRectype * r = new_body_record(lognum(i));
|
2001-04-30 15:04:10 +00:00
|
|
|
|
set_body_key(*r);
|
|
|
|
|
b->set_key(r);
|
1997-06-13 14:00:54 +00:00
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
if (_autoload[i])
|
1998-04-30 15:09:06 +00:00
|
|
|
|
load_rows_file(lognum(i));
|
1997-06-13 14:00:54 +00:00
|
|
|
|
else
|
|
|
|
|
if (_files.objptr(i) != NULL)
|
1998-04-30 15:09:06 +00:00
|
|
|
|
_changed.set(i);
|
1997-06-13 14:00:54 +00:00
|
|
|
|
}
|
1997-06-06 16:37:06 +00:00
|
|
|
|
}
|
1997-06-03 16:06:27 +00:00
|
|
|
|
}
|
|
|
|
|
|
1997-08-18 16:03:20 +00:00
|
|
|
|
// @mfunc Copia il multiple rectype r su quello corrente
|
|
|
|
|
TMultiple_rectype & TMultiple_rectype::copy(const TMultiple_rectype& r)
|
|
|
|
|
{
|
|
|
|
|
// copia..
|
1997-10-02 16:56:32 +00:00
|
|
|
|
TAuto_variable_rectype::operator=((TAuto_variable_rectype&)r);
|
1998-04-30 15:09:06 +00:00
|
|
|
|
|
|
|
|
|
_nuovo = r._nuovo;
|
|
|
|
|
_files = r._files;
|
|
|
|
|
_logicnums = r._logicnums;
|
|
|
|
|
_changed = r._changed;
|
|
|
|
|
_autoload = r._autoload;
|
|
|
|
|
_numfields = r._numfields;
|
|
|
|
|
|
1997-08-18 16:03:20 +00:00
|
|
|
|
return *this;
|
|
|
|
|
}
|
1997-07-28 09:41:46 +00:00
|
|
|
|
|
2006-04-13 17:56:02 +00:00
|
|
|
|
// @mfunc Ritorna il numero di righe caricate
|
1997-08-18 16:03:20 +00:00
|
|
|
|
int TMultiple_rectype::loaded_rows(int logicnum) const
|
|
|
|
|
{
|
|
|
|
|
const int index = log2ind(logicnum);
|
1999-02-02 08:43:43 +00:00
|
|
|
|
TRecord_array* r = (TRecord_array*) ((TMultiple_rectype *) this)->_files.objptr(index);
|
2006-04-13 17:56:02 +00:00
|
|
|
|
if (_changed[index] || r == NULL)
|
1997-08-18 16:03:20 +00:00
|
|
|
|
return 0;
|
2006-04-13 17:56:02 +00:00
|
|
|
|
|
1997-08-18 16:03:20 +00:00
|
|
|
|
return r->rows();
|
|
|
|
|
}
|
1997-07-28 09:41:46 +00:00
|
|
|
|
|
1998-11-04 18:04:26 +00:00
|
|
|
|
// @mfunc confronta due record multipli
|
2000-10-03 13:45:12 +00:00
|
|
|
|
// Affidabilit<69> 95%
|
1998-11-04 18:04:26 +00:00
|
|
|
|
int TMultiple_rectype::compare(const TSortable& s) const
|
|
|
|
|
{
|
|
|
|
|
int res = TRectype::compare(s);
|
|
|
|
|
TMultiple_rectype & m = (TMultiple_rectype &) s;
|
1999-02-02 08:43:43 +00:00
|
|
|
|
|
1998-11-10 10:07:12 +00:00
|
|
|
|
for (int i = 0 ; res == 0 && i < _logicnums.items(); i++)
|
1998-11-04 18:04:26 +00:00
|
|
|
|
{
|
1998-11-10 10:07:12 +00:00
|
|
|
|
const int logicnum = lognum(i);
|
1998-11-04 18:04:26 +00:00
|
|
|
|
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))
|
|
|
|
|
{
|
1999-02-02 08:43:43 +00:00
|
|
|
|
res = j - k; // Controlla che non ci siano salti
|
1998-11-04 18:04:26 +00:00
|
|
|
|
if (res == 0)
|
1999-02-02 08:43:43 +00:00
|
|
|
|
res = r[j].compare(r1[j]);
|
1998-11-04 18:04:26 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return res;
|
|
|
|
|
}
|
|
|
|
|
|
2000-10-03 13:45:12 +00:00
|
|
|
|
// @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);
|
2001-05-04 10:59:04 +00:00
|
|
|
|
const int last = _logicnums.last(); // qui
|
|
|
|
|
for (int i = 0; yes && i < last; i++)
|
2000-10-03 13:45:12 +00:00
|
|
|
|
{
|
2001-05-04 10:59:04 +00:00
|
|
|
|
const int logicnum = lognum(i);
|
2000-10-03 13:45:12 +00:00
|
|
|
|
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;
|
|
|
|
|
}
|
|
|
|
|
|
1997-06-03 16:06:27 +00:00
|
|
|
|
int TMultiple_rectype::remove(TBaseisamfile & f) const
|
|
|
|
|
{
|
|
|
|
|
int err = NOERR;
|
2004-03-16 10:08:50 +00:00
|
|
|
|
for (int i = _logicnums.last(); err == NOERR && i >= 0 ; i = _logicnums.pred(i))
|
1997-06-03 16:06:27 +00:00
|
|
|
|
{
|
1998-04-30 15:09:06 +00:00
|
|
|
|
TRecord_array & r = body(lognum(i));
|
1997-06-13 14:00:54 +00:00
|
|
|
|
err = r.remove();
|
1997-06-03 16:06:27 +00:00
|
|
|
|
}
|
|
|
|
|
if (err == NOERR)
|
|
|
|
|
err = TRectype::remove(f);
|
|
|
|
|
return err;
|
|
|
|
|
}
|
|
|
|
|
|
2000-05-05 15:25:49 +00:00
|
|
|
|
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);
|
2001-05-04 10:59:04 +00:00
|
|
|
|
const int last = _logicnums.last(); // qui
|
|
|
|
|
for (int i = 0; i < last; i++)
|
2000-05-05 15:25:49 +00:00
|
|
|
|
{
|
2001-05-04 10:59:04 +00:00
|
|
|
|
TRecord_array& b = body(lognum(i));
|
2000-05-05 15:25:49 +00:00
|
|
|
|
for (int r = 1; b.exist(r); r++)
|
|
|
|
|
b[r].fill_transaction(cfg, r);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
1997-06-03 16:06:27 +00:00
|
|
|
|
// @doc INTERNAL
|
|
|
|
|
TMultiple_rectype::TMultiple_rectype(int hfn)
|
1998-04-30 15:09:06 +00:00
|
|
|
|
: TAuto_variable_rectype(hfn), _nuovo(TRUE)
|
1997-06-03 16:06:27 +00:00
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
1997-06-09 09:34:12 +00:00
|
|
|
|
void TMultiple_rectype::enable_autoload(int logicnum,bool on)
|
|
|
|
|
{
|
|
|
|
|
const int index = log2ind(logicnum);
|
1998-04-30 15:09:06 +00:00
|
|
|
|
_autoload.set(index, on);
|
1997-06-09 09:34:12 +00:00
|
|
|
|
}
|
1997-06-27 09:13:03 +00:00
|
|
|
|
|
|
|
|
|
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)
|
|
|
|
|
{
|
2006-04-13 17:56:02 +00:00
|
|
|
|
TRecord_array& b = body(logicnum);
|
|
|
|
|
TRectype& r = b.row(-1, true);
|
1997-06-27 09:13:03 +00:00
|
|
|
|
|
|
|
|
|
return r;
|
|
|
|
|
}
|
1997-06-09 09:34:12 +00:00
|
|
|
|
|
|
|
|
|
bool TMultiple_rectype::autoload_enabled(int logicnum)
|
|
|
|
|
{
|
|
|
|
|
return _autoload[log2ind(logicnum)];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// @cmember Aggiunge il corpo lgicnum
|
1998-04-30 15:09:06 +00:00
|
|
|
|
void TMultiple_rectype::add_file(int logicnum, const char* numfield)
|
1997-06-03 16:06:27 +00:00
|
|
|
|
{
|
1998-04-30 15:09:06 +00:00
|
|
|
|
_logicnums.add_long(logicnum);
|
|
|
|
|
_numfields.add(numfield);
|
1997-06-03 16:06:27 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
TMultiple_rectype::TMultiple_rectype(const TBaseisamfile* file)
|
1998-04-30 15:09:06 +00:00
|
|
|
|
:TAuto_variable_rectype(file), _nuovo(TRUE)
|
1997-06-03 16:06:27 +00:00
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// @ cmember costruttore dal record
|
|
|
|
|
TMultiple_rectype::TMultiple_rectype(const TRectype & rec)
|
1998-04-30 15:09:06 +00:00
|
|
|
|
:TAuto_variable_rectype(rec), _nuovo(TRUE)
|
1997-06-03 16:06:27 +00:00
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// @mfunc costruttore di copia
|
|
|
|
|
TMultiple_rectype::TMultiple_rectype(const TMultiple_rectype& r)
|
1997-08-18 16:03:20 +00:00
|
|
|
|
:TAuto_variable_rectype(r)
|
1997-06-03 16:06:27 +00:00
|
|
|
|
{
|
|
|
|
|
// copia..
|
1997-08-18 16:03:20 +00:00
|
|
|
|
copy(r);
|
1997-06-03 16:06:27 +00:00
|
|
|
|
}
|
|
|
|
|
|