diff --git a/include/isam.cpp b/include/isam.cpp index 96ad4b2a6..3b47b8dcd 100755 --- a/include/isam.cpp +++ b/include/isam.cpp @@ -2527,6 +2527,11 @@ int TRectype::remove(TBaseisamfile& f) const return f.remove(*this); } +void TRectype::renum_key(const char* field, const char* val) +{ + put(field, val); +} + // Certified 99% TRectype& TRectype::operator =(const char* rec) { diff --git a/include/isam.h b/include/isam.h index f172cf087..b9c94e585 100755 --- a/include/isam.h +++ b/include/isam.h @@ -78,6 +78,7 @@ public: // TObject virtual int write(TBaseisamfile& f) const; virtual int rewrite(TBaseisamfile& f) const; virtual int remove(TBaseisamfile& f) const; + virtual void renum_key(const char* field, const char* val); public: // FPUB diff --git a/include/relation.cpp b/include/relation.cpp index 20ce32e35..fe3f27da9 100755 --- a/include/relation.cpp +++ b/include/relation.cpp @@ -1,4 +1,4 @@ -// $Id: relation.cpp,v 1.64 1995-09-14 13:12:18 alex Exp $ +// $Id: relation.cpp,v 1.65 1995-09-19 15:45:37 guy Exp $ // relation.cpp // fv 12/8/93 // relation class for isam files @@ -1170,8 +1170,8 @@ bool TCursor::is_first_match(int ln) /////////////////////////////////////////////////////////// typedef struct { - char f[512]; - TRecnotype p; + char f[512]; + TRecnotype p; } El_To_Sort; bool TSorted_cursor::check_expr(TString& s) @@ -1182,45 +1182,45 @@ bool TSorted_cursor::check_expr(TString& s) // dopo l'operatore UPPER(). E' a cura delle altre funzioni esterne che utilizzano la check_expr() // discriminare il segno + o - che sia { - int p=s.find('('); - int p1=s.find(')'); - int rt=TRUE; - - if (p>-1 && p1>-1) - if (s.find("UPPER") == -1) - { - error_box("Only UPPER() operator is allowed"); - rt=FALSE; - } - else - { - s=s.mid(6,s.len()-7); - p=s.find('('); - p1=s.find(')'); - if (p>-1 || p1 >-1) - { - error_box("Too many parentheses!"); - rt=FALSE; - } - } + int p=s.find('('); + int p1=s.find(')'); + int rt=TRUE; + + if (p>-1 && p1>-1) + if (s.find("UPPER") == -1) + { + error_box("Only UPPER() operator is allowed"); + rt=FALSE; + } + else + { + s=s.mid(6,s.len()-7); + p=s.find('('); + p1=s.find(')'); + if (p>-1 || p1 >-1) + { + error_box("Too many parentheses!"); + rt=FALSE; + } + } else - if ((p>-1 && p1==-1) || (p==-1 && p1>-1)) - { - error_box("Unbalanced parentheses in expression"); - rt=FALSE; - } - return rt; + if ((p>-1 && p1==-1) || (p==-1 && p1>-1)) + { + error_box("Unbalanced parentheses in expression"); + rt=FALSE; + } + return rt; } bool TSorted_cursor::is_upper(TString& s) // Controlla se nell'espressione esiste l'operatore UPPER() { - bool rt=TRUE; - if (s.find("UPPER")>-1) - rt=check_expr(s); - else - rt=FALSE; - return rt; + bool rt=TRUE; + if (s.find("UPPER")>-1) + rt=check_expr(s); + else + rt=FALSE; + return rt; } TRecnotype TSorted_cursor::buildcursor(TRecnotype rp) @@ -1234,9 +1234,9 @@ TRecnotype TSorted_cursor::buildcursor(TRecnotype rp) _order_expr.restart(); while ((s=_order_expr.get()).not_empty()) { - check_expr(s); // Toglie l'eventuale operatore UPPER(), in modo che l'ultimo carattere - // indichi eventualmente la direzione dell'ordinamento - char versus = (s.right(1)=="-") ? 'd' : 'a'; + check_expr(s); // Toglie l'eventuale operatore UPPER(), in modo che l'ultimo carattere + // indichi eventualmente la direzione dell'ordinamento + char versus = (s.right(1)=="-") ? 'd' : 'a'; if (s.right(1) == "-" || s.right(1) == "+") s.cut(s.len()-1); TFieldref f(s,0); @@ -1290,7 +1290,7 @@ TRecnotype TSorted_cursor::buildcursor(TRecnotype rp) ap += pagecnt; pagecnt = 0; } - page[pagecnt++] = recno; // lasciare cosi' altrimenti la readat legge due volte lo stesso record + page[pagecnt++] = recno; // lasciare cosi' altrimenti la readat legge due volte lo stesso record DB_index_next(file().filehnd()->fhnd); int rt=get_error(-1); if (rt != NOERR) @@ -1311,15 +1311,15 @@ TRecnotype TSorted_cursor::buildcursor(TRecnotype rp) pagecnt=0; while ((Element=(El_To_Sort *)_sort->retrieve()) != NULL) { - page[pagecnt++]=Element->p; - if (pagecnt==CMAXELPAGE) - { - fwrite(page,sizeof(TRecnotype),pagecnt,_f); - pagecnt=0; - } + page[pagecnt++]=Element->p; + if (pagecnt==CMAXELPAGE) + { + fwrite(page,sizeof(TRecnotype),pagecnt,_f); + pagecnt=0; + } } if (pagecnt) - fwrite(page,sizeof(TRecnotype),pagecnt,_f); + fwrite(page,sizeof(TRecnotype),pagecnt,_f); if (TCursor::pos() == -1) pos=0; delete page; fclose (_f); @@ -1353,15 +1353,15 @@ int TSorted_cursor::filtercursor(int pagecnt, TRecnotype* page) if (p>-1) // rimane solo l'indicazione del file (eventuale) s.cut(p); // ed il nome del campo: else // UPPER(20->RAGSOC[1,30]+) ===>> 20->RAGSOC - if (s.right(1) == "-" || s.right(1) == "+") - s.cut(s.len()-1); + if (s.right(1) == "-" || s.right(1) == "+") + s.cut(s.len()-1); TFieldref f(s,0); TString sf=f.read(relation()); TFieldtypes fld_type = file(f.file()).curr().type(s); if (fld_type == _datefld) // Se il campo e' di tipo data, la converte in ANSI! { - TDate d(sf); - sf=d.string(ANSI); + TDate d(sf); + sf=d.string(ANSI); } if (is_up) sf.upper(); TString fmt; @@ -1385,14 +1385,14 @@ bool TSorted_cursor::changed() if (_is_valid_expr) { - rt = TCursor::changed(); - if (!rt) rt=_is_changed_expr; - _is_changed_expr = FALSE; + rt = TCursor::changed(); + if (!rt) rt=_is_changed_expr; + _is_changed_expr = FALSE; } else - { - error_box("Can't perform changed() while expression ain't valid!"); - rt=FALSE; - } + { + error_box("Can't perform changed() while expression ain't valid!"); + rt=FALSE; + } return rt; } @@ -1602,7 +1602,7 @@ TRecord_array::TRecord_array(const TRectype& r, const char* numfield, int first) TRecord_array::TRecord_array(int logicnum, const char* numfield, int first) : _file(logicnum), _num(numfield), _offset(first - 1) { - add(new TRectype(logicnum)); + set_key(new TRectype(logicnum)); } TRecord_array::TRecord_array(const TRecord_array& a) @@ -1611,15 +1611,16 @@ TRecord_array::TRecord_array(const TRecord_array& a) 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 int numkey = 0; // Memento! Gli indici delle chiavi partono da zero! const RecDes* recd = r->rec_des(); // Descrizione del record della testata - const KeyDes& kd = recd->Ky[numkey]; // Elenco dei campi chaive + 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 = recd->Ky[numkey].NkFields-1; i >= 0; i--) + for (int i = kd.NkFields-2; i >= 0; i--) { const int nf = kd.FieldSeq[i] % MaxFields; const RecFieldDes& rf = recd->Fd[nf]; @@ -1652,7 +1653,8 @@ TRectype& TRecord_array::row(int n, bool create) { r = (TRectype*)key().dup(); // Crea nuovo record copiando la chiave n = add(r, i) + _offset; // Riassegna n se era negativo! - r->put(_num, n); // Aggiorna campo numero riga + char str[8]; sprintf(str, "%d", n); + r->renum_key(_num, str); // Aggiorna campo numero riga } CHECKD(r && n > 0, "Bad record number ", n); return *r; @@ -1660,17 +1662,15 @@ TRectype& TRecord_array::row(int n, bool create) bool TRecord_array::renum_key(const char* field, const TString& num) { - CHECKS(!num.blank(), "Blank key value for 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->put(field, num); + if (r != NULL) + r->renum_key(field, num); } return TRUE; @@ -1734,12 +1734,12 @@ int TRecord_array::read(TRectype* filter) CHECKS(filter->get(_num).empty(), "You can't specify in the filter the field ", (const char*)_num); destroy(); - set_key(filter); // Store filter record for later use - int err = NOERR; - if (!filter->empty()) + 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 && *rec == *filter; e = rec->next(f)) @@ -1758,14 +1758,41 @@ int TRecord_array::read(const TRectype& filter) 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 && *rec == key(); 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); - - int last_on_file = 0; - const int u = last(); for (int i = 1; i <= u; i++) { @@ -1785,7 +1812,10 @@ int TRecord_array::write(bool re) const { err = r->write(f); if (err == _isreinsert) + { err = r->rewrite(f); + re = TRUE; + } if (err != NOERR) break; } @@ -1796,9 +1826,10 @@ int TRecord_array::write(bool re) const if (pos > last_on_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) // La riga c'era ma ora non piu' + if (err == NOERR && *rec == key()) // La riga c'era ma ora non piu' { last_on_file = atoi(rec->get(_num)); if (last_on_file == pos) @@ -1812,34 +1843,22 @@ int TRecord_array::write(bool re) const } } else - last_on_file = 30000; + last_on_file = EOR; delete rec; } } } - if (re && err == NOERR && last_on_file != 30000) - { - const int pos = i+_offset; - TRectype* rec = (TRectype*)key().dup(); - // Cancella eventuali residui successivi - rec->put(_num, pos); - for (int e = rec->read(f, _isgteq); e == NOERR && *rec == key(); e = rec->next(f)) - { - err = rec->remove(f); - if (err != NOERR) - break; - } - delete rec; - } + // Cancella eventuali residui successivi + if (err == NOERR && last_on_file != EOR) + remove_from(i + _offset); return err; } -int TRecord_array::remove() +int TRecord_array::remove() const { - destroy_rows(); - return rewrite(); + return remove_from(1 + _offset); } /////////////////////////////////////////////////////////// diff --git a/include/relation.h b/include/relation.h index 388dbf615..1ccfafd62 100755 --- a/include/relation.h +++ b/include/relation.h @@ -1,4 +1,4 @@ -/* $Id: relation.h,v 1.27 1995-08-28 07:51:30 guy Exp $ */ +/* $Id: relation.h,v 1.28 1995-09-19 15:45:42 guy Exp $ */ // join.h // fv 12/8/93 // join class for isam files @@ -138,6 +138,7 @@ class TRecord_array : private TArray protected: int rec2row(const TRectype& r) const; // Estrae il numero riga di un record const TString& num_field() const { return _num; } + int remove_from(int i) const; public: const TRectype& key() const; @@ -160,6 +161,7 @@ public: virtual bool destroy_row(const TRectype& r, bool pack = FALSE) { return destroy_row(rec2row(r), pack); } void destroy_rows(); // Cancella tutte le righe + int logic_num() const { return _file; } void set_key(TRectype* r); // Cambia l'intera chiave (solo se vuoto!) bool renum_key(const char* field, const TString& num); bool renum_key(const char* field, long num); // Rinumera campo chiave in seguito a reinsert @@ -168,7 +170,7 @@ public: virtual int read(TRectype* r); // Leggi tutto l'array da file virtual int write(bool re = FALSE) const; // Aggiorna il file virtual int rewrite() const { return write(TRUE); } - virtual int remove(); // Cancella tutti i record dal file + virtual int remove() const; // Cancella tutti i record dal file TRecord_array(const TRectype& r, const char* numfield, int first = 1); TRecord_array(int logicnum, const char* numfield, int first = 1);