/* $Id: relation.h,v 1.2 1994-08-26 14:06:07 alex Exp $ */ // join.h // fv 12/8/93 // join class for isam files #ifndef __RELATION_H #define __RELATION_H #ifndef __ISAM_H #include #endif #ifndef __ARRAY_H #include #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(byte 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 = 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 = 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(int logicnum, const char* relexprs, int key = 1, int linkto = 0, byte alias = 0, bool allow_lock = FALSE); bool add(const char* tabname, const char* relexprs, int key = 1, int linkto = 0, byte alias = 0, bool allow_lock = FALSE); // @DES write methods // @FPUB virtual int write (bool force = TRUE, TDate& atdate = botime); virtual int rewrite(bool force = TRUE, TDate& atdate = botime); virtual int remove (TDate& atdate = 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(); } TRelation(int logicnum, bool linkrecinst = TRUE); TRelation(const char* tabname, bool linkrecinst = TRUE); virtual ~TRelation(); }; // @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) const; 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); // Assegnazione TCursor& operator +=(const TRecnotype nr); // Scorri avanti TCursor& operator -=(const TRecnotype nr); // Scorri indietro TCursor& operator ++(); // Avanti di un record TCursor& operator --(); // Indietro di un record 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 = botime); 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, TRectype* from = NULL, 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 TString16 _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