campo-sirio/include/relation.h

317 lines
12 KiB
C
Raw Normal View History

/* $Id: relation.h,v 1.14 1995-04-14 12:14:16 guy Exp $ */
// join.h
// fv 12/8/93
// join class for isam files
#ifndef __RELATION_H
#define __RELATION_H
#ifndef __ISAM_H
#include <isam.h>
#endif
// @C
class TRelation : public TObject
{
friend class TRelationdef;
// class TRelation : public TLocalisamfile
// @END
// @DPRIV
TToken_string _status; // stato della relazione
TArray _files; // file descriptors
TArray _reldefs; // TRelationdef array
int _errors;
// @END
// @FPROT
protected:
virtual void print_on(ostream& out) const;
int log2ind(int logicnum) const;
int alias2ind(int alias) const;
int name2ind(const char* name) const;
TRelationdef& reldef(int i) const { return (TRelationdef&)_reldefs[i]; }
TLocalisamfile& file(int i = 0) const { return (TLocalisamfile&)_files[i]; }
// @LONGDES
// position_rels fa tutto il lavoro: se non trova un record
// adatto su un file, svuota il record corrente e non ritorna errore.
// write etc. poi procedono normalmente
// @END
int position_rels(TIsamop op = _isequal, TReclock lockop = _nolock, TDate& atdate = (TDate&)botime, int first = 0);
friend class TCursor;
public:
// @FPUB
int update() { return position_rels(_isequal, _nolock);}
void zero();
virtual int next(TReclock lockop = _nolock) { return file().next(lockop) == NOERR ? position_rels(_isequal, lockop) : file().status(); }
virtual int prev(TReclock lockop = _nolock) { return file().prev(lockop) == NOERR ? position_rels(_isequal, lockop) : file().status(); }
virtual int next(TDate& atdate) { return file().next(atdate) == NOERR ? position_rels(_isequal, _nolock, atdate) : file().status(); }
virtual int prev(TDate& atdate) { return file().prev(atdate) == NOERR ? position_rels(_isequal, _nolock, atdate) : file().status(); }
virtual int first(TReclock lockop = _nolock) { return file().first(lockop) == NOERR ? position_rels(_isequal, lockop) : file().status(); }
virtual int last(TReclock lockop = _nolock) { return file().last(lockop) == NOERR ? position_rels(_isequal, lockop) : file().status(); }
virtual int skip(TRecnotype nrec, TReclock lockop = _nolock) { return file().skip(nrec, lockop) == NOERR ? position_rels(_isequal, lockop) : file().status(); }
virtual int read(TIsamop op = _isgteq, TReclock lockop = _nolock, TDate& atdate = (TDate&)botime) { return file().read(op, lockop, atdate) == NOERR ? position_rels(_isequal, lockop, atdate) : file().status();}
TLocalisamfile& lfile(int logicnum = 0) const;
TLocalisamfile& lfile(const char* name) const;
void write_enable(int logicnum = -1, const bool on = TRUE) ;
void write_enable(const char* name, const bool on = TRUE) ;
void write_disable(int logicnum = -1) { write_enable(logicnum, FALSE); }
void write_disable(const char* name) { write_enable(name, FALSE); }
TRectype& curr(int logicnum = 0) const { return lfile(logicnum).curr(); }
// next_match for 0ne-to-many relations; positions logicnum (!= main)
// on next matching record; returns TRUE or FALSE if no more matches; in
// any case relation is kept consistent except when inconsistent in
// first place
bool next_match(int logicnum, const char* fieldlist = NULL, int nkey = 0);
// @DES add relation
// @FPUB
bool add(TLocalisamfile* f, const char* relexprs, int key,
int linkto, int alias, bool allow_lock);
bool add(int logicnum, const char* relexprs, int key = 1,
int linkto = 0, int alias = 0, bool allow_lock = FALSE);
bool add(const char* tabname, const char* relexprs, int key = 1,
int linkto = 0, int alias = 0, bool allow_lock = FALSE);
void replace(TLocalisamfile* f, int index = 0);
// @DES write methods
// @FPUB
virtual int write (bool force = TRUE, TDate& atdate = (TDate&)botime);
virtual int rewrite(bool force = TRUE, TDate& atdate = (TDate&)botime);
virtual int remove (TDate& atdate = (TDate&)botime);
// @DES checking methods
// @FPUB
bool eof( int logicnum = 0) { return lfile(logicnum).eof(); }
bool bof( int logicnum = 0) { return lfile(logicnum).bof(); }
// @N
// status(), good() and bad() return the status of the relation when called
// with no args, or the status of the file when called with
// a logical number
// @END
bool status(int logicnum = 0) { return lfile(logicnum).status(); }
bool good( int logicnum = 0) { return lfile(logicnum).good(); }
bool bad( int logicnum = 0) { return lfile(logicnum).bad(); }
bool empty( int logicnum = 0) { return lfile(logicnum).empty(); }
// @END
// @LONGDES
// isconsistent() returns TRUE if every file in the relation is
// OK, current record is non-empty, and relation is consistent.
// If it's not and reset is TRUE, it tries to reset the relation
// to a consistent state (based on main record) -- no further check
// is done.
// Also called internally by update and remove.
// @END
bool isconsistent(bool reset = FALSE);
// TRUE se c'e' un record ed e' il primo match (non si e' mai fatta
// position_rels)
bool is_first_match(int logicnum);
void save_status () ;
void restore_status () ;
// @DES positioning operators. return status
// @FPUB
TRecnotype operator +=(const TRecnotype npos) { return skip(npos); }
TRecnotype operator -=(const TRecnotype npos) { return skip(-npos); }
TRecnotype operator ++() { return next(); }
TRecnotype operator --() { return prev(); }
void print_on(TArray& a) const; // Mette la descrizione in un array di TToken_string
TRelation(int logicnum, bool linkrecinst = FALSE);
TRelation(const char* tabname, bool linkrecinst = FALSE);
TRelation(TLocalisamfile* f);
virtual ~TRelation();
};
///////////////////////////////////////////////////////////
// TRecord_Array
///////////////////////////////////////////////////////////
class TRecord_array : private TArray
{
int _file; // Numero logico del file principale
TString16 _num; // Nome del campo col numero di riga
private:
int rec2row(const TRectype& r) const; // Estrae il numero riga di un record
const TRectype& key() const { return (const TRectype&)operator[](0); }
public:
int rows() const { return items()-1; } // Numero di righe presenti
int last_row() const { return last(); } // Ultima riga
const TRectype& row(int r) const // Ennesima riga costante
{ CHECKD(r > 0, "Bad record number ", r); return (const TRectype&)operator[](r); }
TRectype& row(int r, bool create); // Ennesima riga
virtual int add_row(const TRectype& r); // Aggiungi/cambia una riga
virtual bool destroy_row(int n, bool pack = FALSE); // Cancella una riga
virtual bool destroy_row(const TRectype& r, bool pack = FALSE) { return destroy_row(rec2row(r), pack); }
void destroy_rows(); // Cancella tutte le righe
bool renum_key(const char* field, const TString& num);
bool renum_key(const char* field, long num); // Rinumera campo chiave in seguito a reinsert
virtual int read(const TRectype& r); // Leggi tutto l'array da file
virtual int write(bool re = FALSE); // Aggiorna il file
virtual int rewrite() { return write(TRUE); }
virtual int remove(); // Cancella tutti i record dal file
TRecord_array(const TRectype& r, const char* numfield);
TRecord_array(int logicnum, const char* numfield);
};
// @C
// Classe TCursor : public TObject
//
// @END
class TExpression;
typedef bool (*FILTERFUNCTION)(const TRelation* r);
class TCursor : public TObject
{
// @DPRIV
TRelation* _if;
int _nkey;
TRecnotype _pos; // Posizione corrente
TRecnotype _totrec;
TRecnotype _lastrec;
TRecnotype _lastkrec;
TFilename _filename;
TString _filter; // Filtro
TString _keyfrom; // chiave iniziale
TString _keyto; // chiave finale
TExpression* _fexpr; // Espressione relativo filtro
bool _frozen;
FILTERFUNCTION _filterfunction;
TFilename _indexname;
// @END
// @FPRIV
virtual TRecnotype buildcursor(TRecnotype rp);
int filtercursor(int pagecnt, TRecnotype* page);
bool changed();
FILE* open_index(bool create = FALSE);
TRecnotype update();
protected:
TRecnotype readrec();
void filter(const char* filter, const TRectype* from = NULL,
const TRectype* to = NULL);
public:
// @FPUB
TRecnotype operator =(const TRecnotype nr); // Va alla posizione nr
TRecnotype operator +=(const TRecnotype nr);
TRecnotype operator -=(const TRecnotype npos) { return operator +=(-npos); }
TRecnotype operator ++() { return operator +=(1); }
TRecnotype operator --() { return operator -=(1); }
TRecnotype pos() const { return _pos; }
TRecnotype items();
TRecnotype size() const { return file().eod(); }
const TString& from() const { return _keyfrom; }
const TString& to() const { return _keyto; }
TRectype& curr(int log = 0) const { return _if->curr(log); }
TRectype& curr(const char * tab) const { return _if->lfile(tab).curr(); }
TRecnotype read(TIsamop op = _isgteq, TReclock lockop = _nolock, TDate& atdate = (TDate&)botime);
int lock(TReclock = _lock);
int unlock() { return lock(_unlock); }
virtual bool ok() const;
const char* filter() const { return _filter; }
void freeze(bool on = TRUE) { _frozen = on; }
bool frozen() const { return _frozen; }
void setfilter(const char* filter_expr) { filter(filter_expr); }
void setregion(const TRectype& from, const TRectype& to)
{ filter(NULL,&from, &to); }
TRelation* relation() const { return _if; }
TLocalisamfile& file(int lnum = 0) const { return _if->lfile(lnum); }
TLocalisamfile& file(const char* name) const { return _if->lfile(name); }
int repos() { return _if->position_rels(); }
void setkey() { file().setkey(_nkey); }
void setkey(int nkey);
int key() const { return _nkey; }
bool next_match(int lognum, const char* fl = NULL, int nk = 0);
bool is_first_match(int ln);
void set_filterfunction(FILTERFUNCTION ff) { _filterfunction = ff; _lastrec = 0L;}
bool has_filter() const { return _filter.not_empty() || _filterfunction; }
void save_status () { _if->save_status(); }
void restore_status () { _if->restore_status(); }
TCursor(TRelation* f, const char* filter = "", int key = 1, const TRectype* from = NULL, const TRectype* to = NULL);
virtual ~TCursor();
};
// @C
// Classe TFieldref : public TObject
// @END
class TFieldref : public TObject
{
// @DPRIV
short _fileid; // Numero del file
TString16 _id; // Nome tabella o stringa col numero del file
TString80 _name; // Nome del campo
int _from, _to; // Substring
protected:
virtual void print_on(ostream& out) const;
public:
// @FPUB
TFieldref();
TFieldref(const TString&, short defid);
TFieldref& operator =(const TString& s); // Operatore di assegnazione
virtual bool ok() const { return _name.not_empty(); } // Vero se il numero del file e' valido
int file() const { return _fileid; } // ritorna il file
const char* name() const { return (const char*) _name; } // ritorna il nome del campo
int from() const { return _from; }
int to() const { return _to; }
int len(TRectype &rec) const;
const char* read(const TRelation* = NULL) const;
const char* read(const TRectype&) const;
void write(const char* val, TRelation* = NULL) const;
void write(const char* val, TRectype& rec) const;
};
// Converte una stringa in numero logico o numero tabella
int name2log(const char* name);
#endif
// ** EOF relation.h