#include 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 & 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 && myself.renum()) myself.renum_key(); } while (err == _isreinsert); myself._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::readat(TBaseisamfile& f, TRecnotype nrec, word lockop) { int err = NOERR; _nuovo = FALSE; 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) { TRectype r(*this); err = TRectype::read(f, op, lockop); if (err != NOERR) { *this = r; _nuovo = TRUE; } } else err = TRectype::read(f, op, lockop); synchronize_bodies(); return err; } void TMultiple_rectype::synchronize_bodies() { 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; } } } // @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); _files = r._files; _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; 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(); } 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) { // copia.. copy(r); }