diff --git a/include/relation.cpp b/include/relation.cpp index a6cadc39f..1ea2141d3 100755 --- a/include/relation.cpp +++ b/include/relation.cpp @@ -1839,386 +1839,6 @@ int TFieldref::len(TRectype &rec) const return len - _from; } -/////////////////////////////////////////////////////////// -// TRecord_Array -/////////////////////////////////////////////////////////// - -TRecord_array::TRecord_array(const TRectype& r, const char* numfield, int first) -: _file(r.num()), _num(numfield), _offset(first - 1) -{ - read(r); -} - -TRecord_array::TRecord_array(int logicnum, const char* numfield, int first) - : _file(logicnum), _num(numfield), _offset(first - 1) -{ - set_key(new TRectype(logicnum)); -} - -TRecord_array::TRecord_array(const TRecord_array& a) - : TArray(a), _file(a._file), _offset(a._offset), _num(a._num) -{} - -TRecord_array::~TRecord_array() -{ -} - -void TRecord_array::set_key(TRectype* r) -{ - CHECK(r != NULL, "TRecord_array can't have a null key"); - CHECK(r->num() == _file, "Bad key record"); - - add(r, 0); // Setta il nuovo campo chiave - if (rows() > 0) - { - const RecDes* recd = r->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 = r->get(rf.Name); - renum_key(rf.Name, val); - } - } -} - -const TRectype& TRecord_array::key() const -{ - TRectype* r = (TRectype*)objptr(0); - CHECK(r, "TRecord_array lost its key"); - return *r; -} - -bool TRecord_array::exist(int n) const -{ - const int i = n > 0 ? n - _offset : -1; - TObject* r = objptr(i); - return r != NULL; -} - -// @doc EXTERNAL - -// @mfunc Ritorna la riga

-esima; se tale riga non esiste e se

assume il valore TRUE la riga viene creata -// -// @rdesc Ritorna un TRectype alla riga cercata o eventualemete il reference della nuova creata, -// NULL nel caso non esista e non venga creata. -TRectype& TRecord_array::row( - int n, // @parm Numero della riga da creare - bool create) // @parm Indica se creare una nuova riga se non esiste: - // - // @flag TRUE | Se la riga

non esiste viene creata - // @flag FALSE | Se la riga

non esiste non viene creata - -// @comm Nel caso

sia TRUE e venga richiesta una riga non esistente si crea un nuovo -// record copiando la chiave. -{ - const int i = n >= 0 ? n - _offset : -1; - TRectype* r = (TRectype*)objptr(i); - if (r == NULL && create) - { - r = (TRectype*)key().dup(); // Crea nuovo record copiando la chiave - n = add(r, i) + _offset; // Riassegna n se era negativo! - char str[16]; sprintf(str, "%d", n); - r->renum_key(_num, str); // Aggiorna campo numero riga - } - CHECKD(r && n > 0, "Bad record number ", n); - return *r; -} - -// @doc EXTERNAL - -// @mfunc Rinumera il campo chiave in seguito a reinsert -// -// @rdesc Ritorna se e' stato rinumerato il campo chiave -bool TRecord_array::renum_key( - const char* field, // @parm Campo della chiave a cui assegnare un nuovo valore - const TString& num) // @parm Nuovo valore da assegnare al campo - // @parm long | num | Nuovo valore da assegnare al campo - -// @syntax bool renum_key(const char* field, const TString& num); -// @syntax bool renum_key(const char* field, long num); - -{ - CHECKS(_num != field, "You can't renumber field ", field); - const TString& curr = key().get(field); - if (curr == num) - return FALSE; - - for (int i = last(); i >= 0; i--) - { - TRectype* r = (TRectype*)objptr(i); - if (r != NULL) - r->renum_key(field, num); - } - - return TRUE; -} - -bool TRecord_array::renum_key(const char* field, long num) -{ - CHECKS(num > 0, "Null key value for field: ", field); - TString16 n; n << num; - return renum_key(field, n); -} - - -int TRecord_array::rec2row(const TRectype& r) const -{ - CHECK(r.num() == _file, "Incompatible record"); - const int n = atoi(r.get(_num)) - _offset; // Non e' detto che sia un int! - CHECKD(n >= 0 && n < 30000, "Bad line number in record ", n + _offset); - return n; -} - -int TRecord_array::insert_row(TRectype* r) -{ - const int nr = rec2row(*r); - CHECK(nr > 0, "You cannot insert a new key"); - const bool shift = exist(nr); - insert(r, nr); - if (shift) - { - for (int f = last(); f > nr; f = pred(f)) - { - char n[16]; - TRectype & rec = row(f, FALSE); - - sprintf(n, "%ld", (long)_offset + f); - rec.renum_key(_num, n); - } - } - return nr; -} - -int TRecord_array::add_row(TRectype* r) -{ - const int nr = rec2row(*r); - add(r, nr); - if (nr == 0 && rows() > 0) // Se ho cambiato il record campione - { // e ci sono altre righe ... - for (int f = r->items()-1; f >= 0; f--) - { - const char* fn = r->fieldname(f); - const TString& v = r->get(fn); - if (v.not_empty()) renum_key(fn, v); // ... aggiorna tutte le righe in base - } // ai campi non vuoti del campione - } - return nr; -} - - -// @doc EXTERNAL - -// @mfunc Elimina le righe vuote -void TRecord_array::pack() -{ - TArray::pack(); - - for (int i = size()-1; i > 0; i--) - { - TRectype* r = (TRectype*)objptr(i); - if (r != NULL) - { - TString16 n; n << i+_offset; - r->renum_key(_num, n); - } - } -} - - -// @doc EXTERNAL - -// @mfunc Cancella una riga -// -// @rdesc Ritorna se e' riuscito ad eliminare la riga -bool TRecord_array::destroy_row( - int r, // @parm Numero della riga da eliminare - bool pack) // @parm Indica se compattare gli elementi dell'array (default FALSE) - // @parm const TRectype& | r | Record da eliminare - -// @syntax bool destroy_row(int n, bool pack); -// @syntax bool destroy_row(const TRectype& r, bool pack); - -{ - CHECKD(r > _offset, "Can't destroy row ", r); - const int index = r - _offset; - const bool ok = destroy(index, pack); - - if (ok && pack) - { - for (int i = size()-1; i >= index; i--) - { - TRectype* r = (TRectype*)objptr(i); - if (r != NULL) - { - TString16 n; n << i+_offset; - r->renum_key(_num, n); - } - } - } - return ok; -} - -void TRecord_array::destroy_rows() -{ - for (int i = last(); i > 0; i = pred(i)) - destroy(i); -} - -// @doc EXTERNAL - -// @mfunc Confronta i campi della chiave 1 scartando l'ultimo -// -// @rdesc Ritorna il risulato del confronto: -// -// @flag TRUE | Se i campi sono uguali -// @flag FALSE | Se i campi sono diversi -bool TRecord_array::good( - const TRectype& rec) const // @parm Record di cui confrontare i campi -{ - const bool yes = key().same_key(rec, 1, 1); - return yes; -} - -int TRecord_array::read(TRectype* filter) -{ - CHECKD(filter->num() == _file, "Bad key record ", filter->num()); - CHECKS(filter->get(_num).empty(), "You can't specify in the filter the field ", (const char*)_num); - - destroy(); - int err = NOERR; - if (filter != NULL && !filter->empty()) - { - TLocalisamfile f(_file); - - set_key(filter); - TRectype* rec = (TRectype*)filter->dup(); - err = rec->read(f, _isgteq); - for (int e = err; e == NOERR && good(*rec); e = rec->next(f)) - { - add_row(rec); - rec = (TRectype*)(key().dup()); - } - delete rec; - } - return err; -} - -int TRecord_array::read(const TRectype& filter) -{ - TRectype* f = (TRectype*)filter.dup(); - return read(f); -} - -int TRecord_array::remove_from(int pos) const -{ - int err = NOERR; - - TRectype* rec = (TRectype*)key().dup(); - CHECK(!rec->empty(), "Can't use empty key"); - - TLocalisamfile f(_file); - rec->put(_num, pos); - for (int e = rec->read(f, _isgteq); e == NOERR && good(*rec); e = rec->next(f)) - { - const int found = rec->get_int(_num); - if (found >= pos) - { - err = rec->remove(f); - if (err != NOERR) - break; - pos = found+1; - } - else - break; - } - delete rec; - - return err; -} - - -int TRecord_array::write(bool re) const -{ - const int EOR = 32000; // End of records on file - int last_on_file = 0; // Last record found on file - int err = NOERR; - - TLocalisamfile f(_file); - const int u = last(); - for (int i = 1; i <= u; i++) - { - const TRectype* r = (TRectype*)objptr(i); - - if (r != NULL) - { - if (re) - { - err = r->rewrite(f); - if (err == _iskeynotfound || err == _iseof || err == _isemptyfile) - err = r->write(f); - if (err != NOERR) - break; - } - else - { - err = r->write(f); - if (err == _isreinsert) - { - err = r->rewrite(f); - re = TRUE; - } - if (err != NOERR) - break; - } - } - else - { - const int pos = i+_offset; - - // Se pos < last_on_file sicuramente la read fallira' per cui la riga - // non puo' esistere su file: non esistendo nemmeno in memoria non devo - // fare assolutamente nulla! - if (pos >= last_on_file) // Puo' esistere su file? - { - TRectype* rec = (TRectype*)key().dup(); - CHECK(!rec->empty(), "TRecord_array has an empty key"); - rec->put(_num, pos); - err = rec->read(f, _isgteq); - if (err == NOERR && good(*rec)) // Cerca una riga >= pos sul file - { - last_on_file = atoi(rec->get(_num)); - if (last_on_file == pos) // La riga c'era ma ora non piu' - { - err = (rec->remove(f)); // Cancello il record indesiderato - if (err != NOERR) - { - delete rec; // Orrore! Un errore di cancellazione! - break; - } - } - } - else - last_on_file = EOR; // Sul file non ci sono piu' righe da cancellare - delete rec; - } - } - } - - // Cancella eventuali residui successivi - if (err == NOERR && last_on_file != EOR) - remove_from(i + _offset); - - return err; -} - -int TRecord_array::remove() const -{ - return remove_from(1 + _offset); -} - /////////////////////////////////////////////////////////// // TRelation_description /////////////////////////////////////////////////////////// diff --git a/include/relation.h b/include/relation.h index 26b55e7be..1e051ebfa 100755 --- a/include/relation.h +++ b/include/relation.h @@ -209,124 +209,6 @@ public: }; -/////////////////////////////////////////////////////////// -// TRecord_Array -/////////////////////////////////////////////////////////// - -// @doc EXTERNAL - -// @class TRecord_array | Classe per la gestione di un array di record -// -// @base public | TArray -class TRecord_array : private TArray - -// @author:(INTERNAL) Guido - -// @access:(INTERNAL) Private Member -{ - // @cmember:(INTERNAL) Numero logico del file principale - int _file; - // @cmember:(INTERNAL) Offset iniziale del record array - int _offset; - // @cmember:(INTERNAL) Nome del campo col numero di riga - TString16 _num; - -// @access Protected Member -protected: - // @cmember Ritorna il numero riga del record

- int rec2row(const TRectype& r) const; - // @cmember Ritorna il nome del campo con numero di riga - const TString& num_field() const - { return _num; } - // @cmember Elimina il record di posizione

(ritorna il risultato dell'operazione) - int remove_from(int i) const; - // @cmember Confronta i campi della chiave 1 scartando l'ultimo - bool good(const TRectype& rec) const; - -// @access Public Member -public: - // @cmember Ritorna il record che fa da chiave per tutti gli altri - const TRectype& key() const; - // @cmember Ritorna il numero di righe presenti - int rows() const - { return items()-1; } - - // @cmember Ritorna la riga successiva non vuota a partire da

- int succ_row(int r) const - { return succ(r - _offset) + _offset; } - // @cmember Ritorna la riga precedente non vuota a partire da

- int pred_row(int r) const - { return pred(r - _offset) + _offset; }; - // @cmember Ritorna l'ultma riga non vuota - int last_row() const - { return last() + _offset; } - // @cmember Ritorna la prima riga non vuota - int first_row() const - { return succ_row(0); } - - // @cmember Ritorna il record

-esimo - const TRectype& row(int r) const - { CHECKD(r > _offset, "Bad record number ", r); return (const TRectype&)operator[](r - _offset); } - - // @cmember Controlla se esiste la riga

(TRUE se esiste) - bool exist(int r) const; - // @cmember Ritorna la riga

-esima; se tale riga non esiste e se

assume il valore TRUE la riga viene creata - TRectype& row(int r, bool create); - - // @cmember Inserisce una riga alla posizione indicata nel record, sposta gli altri elementi se la posizione era gia' occupata - virtual int insert_row(TRectype* r); - // @cmember Inserisce una riga alla posizione indicata nel record, sposta gli altri elementi se la posizione era gia' occupata - int insert_row(const TRectype& r) - { return insert_row((TRectype*)r.dup()); } - - // @cmember Aggiunge/sostituisce una riga alla posizione indicata nel record - virtual int add_row(TRectype* r); - // @cmember Aggiunge/sostituisce una riga alla posizione indicata nel record - int add_row(const TRectype& r) - { return add_row((TRectype*)r.dup()); } - // @cmember Compatta le righe piene - virtual void pack() ; - // @cmember Cancella una riga identificata da

- virtual bool destroy_row(int n, bool pack = FALSE); - // @cmember Cancella una riga identificata da

- virtual bool destroy_row(const TRectype& r, bool pack = FALSE) - { return destroy_row(rec2row(r), pack); } - // @cmember Cancella tutte le righe - void destroy_rows(); - - // @cmember Ritorna il numero logico del file principale - int logic_num() const - { return _file; } - // @cmember Cambia l'intera chiave (solo se vuoto) - void set_key(TRectype* r); - // @cmember Rinumera il campo chiave in seguito a reinsert - bool renum_key(const char* field, const TString& num); - // @cmember Rinumera il campo chiave in seguito a reinsert - bool renum_key(const char* field, long num); - - // @cmember Legge tutto l'array dal file - virtual int read(const TRectype& r); - // @cmember Legge tutto l'array dal file - virtual int read(TRectype* r); - // @cmember Aggiorna il file (se

== TRUE allora viene aggiornato il record se esisteva) - virtual int write(bool re = FALSE) const; - // @cmember Aggiorna il record sul file - virtual int rewrite() const - { return write(TRUE); } - // @cmember Cancella tutti i record dal file - virtual int remove() const; - - // @cmember Costruttore - TRecord_array(const TRectype& r, const char* numfield, int first = 1); - // @cmember Costruttore - TRecord_array(int logicnum, const char* numfield, int first = 1); - // @cmember Costruttore - TRecord_array(const TRecord_array& a); - // @cmember Distruttore - virtual ~TRecord_array(); -}; - - class TExpression; // @doc EXTERNAL