745 lines
		
	
	
		
			28 KiB
		
	
	
	
		
			C++
		
	
	
		
			Executable File
		
	
	
	
	
			
		
		
	
	
			745 lines
		
	
	
		
			28 KiB
		
	
	
	
		
			C++
		
	
	
		
			Executable File
		
	
	
	
	
/*      $Id: relation.h,v 1.32 1995-12-29 12:09:12 andrea 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
 | 
						|
 | 
						|
#ifndef __SORT_H
 | 
						|
class TSort;
 | 
						|
#endif
 | 
						|
 | 
						|
// @doc EXTERNAL
 | 
						|
 | 
						|
// @class TRelation | Classe per la definizione delle relazioni esistenti tra i file
 | 
						|
//
 | 
						|
// @base public | TObject
 | 
						|
class TRelation : public TObject
 | 
						|
// @author(:INTERNAL) Sandro
 | 
						|
{
 | 
						|
  // @cfriend TRelationdef
 | 
						|
  friend class TRelationdef;
 | 
						|
  // @cfriend TRelation_description
 | 
						|
  friend class TRelation_description;
 | 
						|
  // @cfriend TCursor
 | 
						|
  friend class TCursor;
 | 
						|
 | 
						|
// @access Provate Member
 | 
						|
 | 
						|
  // @cmember Stato della relazione
 | 
						|
  TToken_string _status;
 | 
						|
  // @cmember Array dei descrittori dei file
 | 
						|
  TArray _files;
 | 
						|
  // @cmember Array di <c TRelationdef>
 | 
						|
  TArray _reldefs;
 | 
						|
  // @cmember Codice dell'ultimo errore occorso
 | 
						|
  int _errors;
 | 
						|
 | 
						|
// @access Protected Member
 | 
						|
protected:
 | 
						|
  // @cmember Ritorna l'indice di <p _files> del numero logico passato
 | 
						|
  int log2ind(int logicnum) const;
 | 
						|
  // @cmember Ritorna l'indice di <p _files> del alias del file passato
 | 
						|
  int alias2ind(int alias) const;
 | 
						|
  // @cmember Ritorna l'indice di <p _files> del nome del file passato
 | 
						|
  int name2ind(const char* name) const;
 | 
						|
 | 
						|
  // @cmember Ritorna la <c TRelationdef> <p i>-esima
 | 
						|
  TRelationdef& reldef(int i) const
 | 
						|
  { return (TRelationdef&)_reldefs[i]; }
 | 
						|
  // @cmember Ritorna il descrittore del file <p i>-esimo
 | 
						|
  TLocalisamfile& file(int i = 0) const
 | 
						|
  { return (TLocalisamfile&)_files[i]; }
 | 
						|
 | 
						|
  // @cmember Permette di posizionare l'albero di relazioni tra i file
 | 
						|
  int position_rels(TIsamop op = _isequal, TReclock lockop = _nolock, TDate& atdate = (TDate&)botime, int first = 0);
 | 
						|
 | 
						|
// @access Public Member
 | 
						|
public:  // TObject
 | 
						|
  // @cmember Controlla se si tratta di un oggetto valido
 | 
						|
  virtual bool ok() const
 | 
						|
  { return good(); }
 | 
						|
  // @cmember Permette di stampare l'oggetto su <p out>
 | 
						|
  virtual void print_on(ostream& out) const;      
 | 
						|
  
 | 
						|
public:
 | 
						|
  // @cmember Aggiorna l'albero delle relazioni
 | 
						|
  int update()
 | 
						|
  { return position_rels(_isequal, _nolock);}
 | 
						|
  // @cmember Azzera l'abero delle relazioni
 | 
						|
  void zero();
 | 
						|
  //@cmember Sposta la relazione sul record successivo del file principale (chiama <mf TRelation::position_rels>)
 | 
						|
  virtual int next(TReclock lockop = _nolock)
 | 
						|
  { return file().next(lockop) == NOERR ? position_rels(_isequal, lockop) : file().status(); }
 | 
						|
  //@cmember Sposta la relazione sul record precedente del file principale (chiama <mf TRelation::position_rels>)
 | 
						|
  virtual int prev(TReclock lockop = _nolock)
 | 
						|
  { return file().prev(lockop) == NOERR ? position_rels(_isequal, lockop) : file().status(); }
 | 
						|
  //@cmember Sposta la relazione sul record successivo del file principale (chiama <mf TRelation::position_rels>)
 | 
						|
  virtual int next(TDate& atdate)
 | 
						|
  { return file().next(atdate) == NOERR ? position_rels(_isequal, _nolock, atdate) : file().status(); }
 | 
						|
  //@cmember Sposta la relazione sul record precedente del file principale (chiama <mf TRelation::position_rels>)
 | 
						|
  virtual int prev(TDate& atdate)
 | 
						|
  { return file().prev(atdate) == NOERR ? position_rels(_isequal, _nolock, atdate) : file().status(); }
 | 
						|
  //@cmember Sposta la relazione sul primo record del file principale (chiama <mf TRelation::position_rels>)
 | 
						|
  virtual int first(TReclock lockop = _nolock)
 | 
						|
  { return file().first(lockop) == NOERR ? position_rels(_isequal, lockop) : file().status(); }
 | 
						|
  //@cmember Sposta la relazione sull'ultimo record del file principale (chiama <mf TRelation::position_rels>)
 | 
						|
  virtual int last(TReclock lockop = _nolock)
 | 
						|
  { return file().last(lockop) == NOERR ? position_rels(_isequal, lockop) : file().status(); }
 | 
						|
  //@cmember Salta <p nrec> posizione dalla corrente sul file principale (chiama <mf TRelation::position_rels>)
 | 
						|
  virtual int skip(TRecnotype nrec, TReclock lockop = _nolock)
 | 
						|
  { return file().skip(nrec, lockop) == NOERR ? position_rels(_isequal, lockop) : file().status(); }
 | 
						|
  //@cmember Legge il record (chiama <mf TRelation::position_rels>)
 | 
						|
  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();}
 | 
						|
 | 
						|
  // @cmember Ritorna il descrittore del file
 | 
						|
  TLocalisamfile& lfile(int logicnum = 0) const;
 | 
						|
  // @cmember Ritorna il descrittore del file
 | 
						|
  TLocalisamfile& lfile(const char* name) const;
 | 
						|
  // @cmember Ritorna il descrittore del file (chiama <mf TRelation::lfile>)
 | 
						|
  TLocalisamfile& operator[] (int logicnum) const 
 | 
						|
  { return lfile(logicnum); }
 | 
						|
 | 
						|
  // @cmember Abilita/disabilita la scrittura dei record collegati sul file
 | 
						|
  void write_enable(int logicnum = 0, const bool on = TRUE) ;
 | 
						|
  // @cmember Abilita/disabilita la scrittura sul file
 | 
						|
  void write_enable(const char* name, const bool on = TRUE) ;
 | 
						|
  // @cmember Disabilita la scrittura sul file (chiama <mf TRelation::write_enable>)
 | 
						|
  void write_disable(int logicnum = 0) 
 | 
						|
  { write_enable(logicnum, FALSE); }
 | 
						|
  // @cmember Disabilita la scrittura sul file (chiama <mf TRelation::write_enable>)
 | 
						|
  void write_disable(const char* name) 
 | 
						|
  { write_enable(name, FALSE); }
 | 
						|
 | 
						|
  // @cmember Ritorna il record corrente del file <p logicnum>
 | 
						|
  //          (chiama <mf TRelation::lfile>)
 | 
						|
  TRectype& curr(int logicnum = 0) const 
 | 
						|
  { return lfile(logicnum).curr(); }
 | 
						|
  // @cmember Posiziona il numero logico sul record successivo
 | 
						|
  bool next_match(int logicnum,  const char* fieldlist = NULL, int nkey = 0);
 | 
						|
 | 
						|
  // @cmember Aggiunge una nuovo file alla relazione partendo dal descrittore del file
 | 
						|
  bool add(TLocalisamfile* f, const char* relexprs, int key, int linkto, int alias, bool allow_lock);
 | 
						|
  // @cmember Aggiunge una nuovo file alla relazione partendo dal numero logico del file
 | 
						|
  bool add(int logicnum, const char* relexprs, int key = 1, int linkto = 0, int alias = 0, bool allow_lock = FALSE);
 | 
						|
  // @cmember Aggiunge una nuovo file alla relazione partendo dal nome della tabella
 | 
						|
  bool add(const char* tabname, const char* relexprs, int key = 1, int linkto = 0, int alias = 0, bool allow_lock = FALSE);
 | 
						|
  // @cmember Sostituisce nella relazione un file
 | 
						|
  void replace(TLocalisamfile* f, int index = 0);
 | 
						|
 | 
						|
  // @cmember Aggiunge il record corrente
 | 
						|
  virtual int write (bool force = TRUE, TDate& atdate = (TDate&)botime);
 | 
						|
  // @cmember Riscrive il record corrente
 | 
						|
  virtual int rewrite (bool force = TRUE, TDate& atdate = (TDate&)botime);
 | 
						|
  // @cmember Elimina il record corrente
 | 
						|
  virtual int remove (TDate& atdate = (TDate&)botime);
 | 
						|
 | 
						|
  // @cmember Controlla se e' stata raggiunta la fine del file
 | 
						|
  //          (se <p logicnum> = 0 dell'intera relazione, altrimenti del file indicato )
 | 
						|
  bool eof( int logicnum = 0) const
 | 
						|
  { return lfile(logicnum).eof(); }
 | 
						|
  // @cmember Controlla se e' stata raggiunta l'inizio del file
 | 
						|
  //          (se <p logicnum> = 0 dell'intera relazione, altrimenti del file indicato )
 | 
						|
  bool bof( int logicnum = 0) const
 | 
						|
  { return lfile(logicnum).bof(); }
 | 
						|
  // @cmember Ritorna lo stao del file indicato (se <p logicnum> = 0 dell'intera relazione, 
 | 
						|
  //				  altrimenti del file indicato )
 | 
						|
  bool status(int logicnum = 0) const
 | 
						|
  { return lfile(logicnum).status(); }
 | 
						|
  // @cmember Controlla se l'ultima operazione sul file e' stat effettuata correttamente
 | 
						|
  //          (se <p logicnum> = 0 dell'intera relazione, altrimenti del file indicato )
 | 
						|
  bool good( int logicnum = 0) const
 | 
						|
  { return lfile(logicnum).good(); }
 | 
						|
  // @cmember Controlla se l'ultima operazione sul file ha generato un errore
 | 
						|
  //          (se <p logicnum> = 0 dell'intera relazione, altrimenti del file indicato )
 | 
						|
  bool bad( int logicnum = 0) const
 | 
						|
  { return lfile(logicnum).bad(); }
 | 
						|
  // @cmember Controlla se e' il file e' vuoto
 | 
						|
  //          (se <p logicnum> = 0 dell'intera relazione, altrimenti del file indicato )
 | 
						|
  bool empty( int logicnum = 0) const
 | 
						|
  { return lfile(logicnum).empty(); }
 | 
						|
 | 
						|
  // @cmember Controlla se la relazione e' corretta
 | 
						|
  bool isconsistent (bool reset = FALSE);
 | 
						|
 | 
						|
  // @cmember Controlla se c'e' un record ed e' il primo match (non si e' mai fatta
 | 
						|
  //          <mf TRelation::position_rels>)
 | 
						|
  bool is_first_match(int logicnum);
 | 
						|
 | 
						|
  // @cmember Ritorna il numero di files collegati
 | 
						|
  int items()
 | 
						|
  { return _reldefs.items(); }
 | 
						|
 | 
						|
  // @cmember Salva la posizione attuale di tutti i file della relazione
 | 
						|
  void save_status () ;
 | 
						|
  // @cmember Ripristina la posizione attuale di tutti i file della relazione
 | 
						|
  void restore_status () ;
 | 
						|
  
 | 
						|
  // positioning operators. return status
 | 
						|
  // @cmember Sposta il puntatore corrente di <p npos> posizioni in avanti
 | 
						|
  //          (ritorna lo stato)
 | 
						|
  TRecnotype operator +=(const TRecnotype npos)
 | 
						|
  { return skip(npos);  }
 | 
						|
  // @cmember Sposta il puntatore corrente di <p npos> posizioni in dietro
 | 
						|
  //          (ritorna lo stato)
 | 
						|
  TRecnotype operator -=(const TRecnotype npos)
 | 
						|
  { return skip(-npos); }
 | 
						|
  // @cmember Sposta il puntatore corrente di una posizione in avanti
 | 
						|
  //          (ritorna lo stato)
 | 
						|
  TRecnotype operator ++()
 | 
						|
  { return next(); }
 | 
						|
  // @cmember Sposta il puntatore corrente di una posizione in dietro
 | 
						|
  //          (ritorna lo stato)
 | 
						|
  TRecnotype operator --()
 | 
						|
  { return prev(); }
 | 
						|
  
 | 
						|
  // @cmember Costruttore dal numero logico del file
 | 
						|
  TRelation(int logicnum);
 | 
						|
  // @cmember Costruttore dal nome della tabella
 | 
						|
  TRelation(const char* tabname);
 | 
						|
  // @cmember Costruttore dal nome del file
 | 
						|
  TRelation(TLocalisamfile* f);
 | 
						|
 | 
						|
  // @cmember Distruttore
 | 
						|
  virtual ~TRelation();
 | 
						|
};
 | 
						|
 | 
						|
 | 
						|
///////////////////////////////////////////////////////////
 | 
						|
// TRecord_Array
 | 
						|
///////////////////////////////////////////////////////////
 | 
						|
 | 
						|
// @class TRecord_array | Classe per la gestione di un array di record
 | 
						|
//
 | 
						|
// @base public | TArray
 | 
						|
class TRecord_array : private TArray
 | 
						|
 | 
						|
// @author(:ITERNAL) Guido
 | 
						|
 | 
						|
// @access Private Member
 | 
						|
{ 
 | 
						|
  // @cmember Numero logico del file principale
 | 
						|
  int _file;
 | 
						|
  // @cmember Offset iniziale del record array
 | 
						|
  int _offset;
 | 
						|
  // @cmember Nome del campo col numero di riga
 | 
						|
  TString16 _num;
 | 
						|
 | 
						|
// @access Protected Member
 | 
						|
protected:
 | 
						|
  // @cmember Ritorna il numero riga del record <p r>
 | 
						|
  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 <p i> (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 prtire da <p r>
 | 
						|
  int succ_row(int r) const 
 | 
						|
  { return succ(r - _offset) + _offset; }
 | 
						|
  // @cmember Ritorna la riga precedente non vuota a prtire da <p r>
 | 
						|
  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 <p r>-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 <p r> (TRUE se esiste)
 | 
						|
  bool exist(int r) const;
 | 
						|
  // @cmember Ritorna la riga <p r>
 | 
						|
  TRectype& row(int r, bool create);
 | 
						|
 | 
						|
  // @cmember Aggiunge/sostituisce una riga  
 | 
						|
  virtual int add_row(TRectype* r);
 | 
						|
  // @cmember Aggiunge un nuovo record all'array
 | 
						|
  int add_row(const TRectype& r) 
 | 
						|
  { return add_row((TRectype*)r.dup()); }
 | 
						|
  // @cmember Cancella una riga identificata da <p n>
 | 
						|
  virtual bool destroy_row(int n, bool pack = FALSE);
 | 
						|
  // @cmember Cancella una riga identificata da <p r>
 | 
						|
  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 <p re> == 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);
 | 
						|
};
 | 
						|
 | 
						|
 | 
						|
class TExpression;
 | 
						|
 | 
						|
// @type FILTERFUNCTION | Controlla se il record debba essere incluso nel cursore
 | 
						|
typedef bool (*FILTERFUNCTION)(const TRelation* r);
 | 
						|
 | 
						|
// @class TCursor | Classe per la definizione di un cursore su di una relazione
 | 
						|
//
 | 
						|
// @base public | TContainer
 | 
						|
class TCursor : public TContainer
 | 
						|
 | 
						|
// @author(:INTERNAL) Villa
 | 
						|
 | 
						|
// @access Private Member
 | 
						|
{
 | 
						|
  // @cmember Relazione su cui costruire il cursore
 | 
						|
  TRelation* _if;
 | 
						|
  // @cmember Chiave del file principale
 | 
						|
  int _nkey;
 | 
						|
  // @cmember Posizione corrente
 | 
						|
  TRecnotype _pos;
 | 
						|
  // @cmember Numero totale di record che verificano il filtro
 | 
						|
  TRecnotype _totrec;
 | 
						|
  // @cmember Numero dell'ultimo record
 | 
						|
  TRecnotype _lastrec;
 | 
						|
  // @cmember Chiave dell'ultimo record
 | 
						|
  TRecnotype _lastkrec; 
 | 
						|
  // @cmember Nome assoluto del file principale
 | 
						|
  TFilename _filename;
 | 
						|
  // @cmember Filtro definito con la <mf TCursor::set_filter>
 | 
						|
  TString _filter;
 | 
						|
  // @cmember Nome della chive iniziale
 | 
						|
  TString _keyfrom;
 | 
						|
  // @cmember Nome della chiave finale
 | 
						|
  TString _keyto;
 | 
						|
  // @cmember Espressione del filtro relativo
 | 
						|
  TExpression* _fexpr;
 | 
						|
  // @cmember Indica se e' stata messa in attesa (non puo' essere modificato)
 | 
						|
  bool _frozen;
 | 
						|
  // @cmember Flag che permette l'update della relazione per l'espressione-filtro
 | 
						|
  bool _filter_update;
 | 
						|
  // @cmember Flag che permette l'update della relazione per la funzione-filtro
 | 
						|
  bool _filterfunction_update;
 | 
						|
  // @cmember Funzione filtro
 | 
						|
  FILTERFUNCTION _filterfunction;
 | 
						|
  // @cmember Nome del file indice
 | 
						|
  TFilename _indexname;
 | 
						|
 | 
						|
  // @cmember Crea (o aggiorna) effettivamente l'indice del cursore
 | 
						|
  TRecnotype update();
 | 
						|
 | 
						|
// @access Protected Member
 | 
						|
protected:
 | 
						|
  // @cmember Apre il file di indice
 | 
						|
  FILE* open_index(bool create = FALSE);
 | 
						|
  // @cmember Ritorna se e' stato modificato il cursore (cioe' quando occorre fare l'update)
 | 
						|
  virtual bool changed();
 | 
						|
  // @cmember Costruisce il cursore a partire dal record
 | 
						|
  virtual TRecnotype buildcursor(TRecnotype rp);
 | 
						|
  // @cmember Permette di creare una pagina di cursori
 | 
						|
  virtual int filtercursor(int pagecnt, TRecnotype* page);
 | 
						|
  // @cmember Posiziona il cursore in modo che il record corrente corriponda alla 
 | 
						|
  //					posizione dell'indice temporaneo
 | 
						|
  TRecnotype readrec();
 | 
						|
  // @cmember Setta il filtro sul cursore
 | 
						|
  void filter(const char* filter, const TRectype* from = NULL, const TRectype* to = NULL);
 | 
						|
  // @cmember Indica se e' possibile fare l'update sulla relazione (se e' possibile
 | 
						|
  //	      sia sull'espressione-filtro che sulla funzione-filtro)
 | 
						|
  bool update_relation() 
 | 
						|
  {return (_filter_update || _filterfunction_update);}
 | 
						|
 | 
						|
// @access Public Member
 | 
						|
public:
 | 
						|
  // @cmember Si sposta alla posizione <p nr>
 | 
						|
  TRecnotype operator =(const TRecnotype nr);
 | 
						|
  // @cmember Si sposta di <p nr> posizioni dalla corrente in avanti
 | 
						|
  TRecnotype operator +=(const TRecnotype nr);        
 | 
						|
  // @cmember Si sposta di <p nr> posizioni dalla corrente in dietro
 | 
						|
  TRecnotype operator -=(const TRecnotype npos) 
 | 
						|
  { return operator +=(-npos); }
 | 
						|
  // @cmember Ritorna il primo oggetto del cursor
 | 
						|
  TObject* first_item( )
 | 
						|
  { operator =( 0 ); return &curr( ); }
 | 
						|
  // @cmember Ritorna l'oggetto del cursor successivo al corrente
 | 
						|
  TObject* succ_item( )
 | 
						|
  { operator +=( 1 ); return &curr( ); }
 | 
						|
  // @cmember Ritorna l'oggetto del cursor precedente al corrente
 | 
						|
  TObject* pred_item( )
 | 
						|
  { operator -=( 1 );  return &curr( );}
 | 
						|
  // @cmember Ritorna l'ultimo oggetto del cursor
 | 
						|
  TObject* last_item( )
 | 
						|
  { operator =( items( ) -1 );  return &curr( ); }
 | 
						|
  // @cmember Ritorna il n8umero di oggetti del cursor
 | 
						|
  long objects( ) 
 | 
						|
  { return items( ); }
 | 
						|
  
 | 
						|
  // @cmember Ritorna la posizione corrente
 | 
						|
  TRecnotype& pos() 
 | 
						|
  { return _pos; }
 | 
						|
  // @cmember  Ritorna il numero totale di record
 | 
						|
  TRecnotype items();
 | 
						|
  // @cmember Ritorna la dimensione del file principale
 | 
						|
  TRecnotype size() const 
 | 
						|
  { return file().eod(); }
 | 
						|
 | 
						|
  // @cmember Ritorna il nome della chiave iniziale
 | 
						|
  const TString& from() const 
 | 
						|
  { return _keyfrom; }
 | 
						|
  // @cmember Ritorna il nome della chiave finale
 | 
						|
  const TString& to() const 
 | 
						|
  { return _keyto; }
 | 
						|
 | 
						|
  // @cmember Ritorna il descrittore del file principale
 | 
						|
  TRectype& curr(int log = 0) const 
 | 
						|
  { return _if->curr(log); }
 | 
						|
  // @cmember Ritorna il descrittore della tabella
 | 
						|
  TRectype& curr(const char * tab) const 
 | 
						|
  { return _if->lfile(tab).curr(); }
 | 
						|
  // @cmember Legge il record
 | 
						|
  TRecnotype read(TIsamop op = _isgteq, TReclock lockop = _nolock, TDate& atdate = (TDate&)botime);
 | 
						|
  // @cmember Mette un lock sul record
 | 
						|
  int lock(TReclock = _lock);
 | 
						|
  // @cmember Toglie un lock sul record (chiama <mf TCursor::lock>)
 | 
						|
  int unlock() 
 | 
						|
  { return lock(_unlock); }
 | 
						|
 | 
						|
  // @cmember Controlla che si tratti di un oggetto valido
 | 
						|
  virtual bool ok() const;
 | 
						|
  // @cmember Ritorna il filtro
 | 
						|
  const char* filter() const 
 | 
						|
  { return _filter; }
 | 
						|
  // @cmember Permette di mettere in attesa il cursore
 | 
						|
  void freeze(bool on = TRUE) 
 | 
						|
  { _frozen = on; }
 | 
						|
  // @cmember Controlla se il cursore e' congelato
 | 
						|
  bool frozen() const 
 | 
						|
  { return _frozen; }
 | 
						|
  // @cmember Permette di modificare l'espressione-filtro
 | 
						|
  void setfilter(const char* filter_expr, bool update=FALSE) 
 | 
						|
  { filter(filter_expr); _filter_update = update; }
 | 
						|
  // @cmember Setta la regione-filtro dal record <p from> al record <p to>
 | 
						|
  void setregion(const TRectype& from, const TRectype& to)
 | 
						|
  { filter(NULL,&from, &to); }
 | 
						|
 | 
						|
  // @cmember Ritorna la relazione del cursore
 | 
						|
  TRelation* relation() const 
 | 
						|
  { return _if; }
 | 
						|
  // @cmember Ritorna il file della relazione con numero logico <p lnum>
 | 
						|
  TLocalisamfile& file(int lnum = 0) const 
 | 
						|
  { return _if->lfile(lnum); }
 | 
						|
  // @cmember Ritorna il file della relazione con nome <p name>
 | 
						|
  TLocalisamfile& file(const char* name) const 
 | 
						|
  { return _if->lfile(name); }
 | 
						|
  // @cmember Riposiziona l'albero delle relazione (chiama <mf TRelation::position_rels>)
 | 
						|
  int repos() 
 | 
						|
  { return _if->position_rels(); }
 | 
						|
 | 
						|
  // @cmember Ritorna l'espressione-filtro
 | 
						|
  TExpression* expression() const 
 | 
						|
  { return _fexpr; }
 | 
						|
  // @cmember Ritorna la funzione-filtro
 | 
						|
  FILTERFUNCTION filterfunction() const 
 | 
						|
  { return _filterfunction; }
 | 
						|
 | 
						|
  // @cmember Setta la chiave del file principale alla chiave del cursore
 | 
						|
  void setkey() 
 | 
						|
  { file().setkey(_nkey); }
 | 
						|
  // @cmember Setta la chiave del file principale alla chiave del cursore
 | 
						|
  void setkey(int nkey);
 | 
						|
  // @cmember Ritorna la chiave del cursor
 | 
						|
  int key() const 
 | 
						|
  { return _nkey; }
 | 
						|
 | 
						|
  // @cmember Posizione il numero logico sul record successivo (chiama <mf TRelation::next_match>)
 | 
						|
  bool next_match(int lognum, const char* fl = NULL, int nk = 0);
 | 
						|
  // @cmember Controlla se c'e' un record ed e' il primo match (chiama <mf TRelation::is_first_match>)
 | 
						|
  bool is_first_match(int ln);
 | 
						|
  
 | 
						|
  // @cmember Setta la fuzione-filtro
 | 
						|
  void set_filterfunction(FILTERFUNCTION ff, bool update=FALSE) 
 | 
						|
  { _filterfunction = ff; _lastrec = 0L; _filterfunction_update = update;}
 | 
						|
  // @cmember Controllla se esiste un fuiltro sul cursor
 | 
						|
  bool has_filter() const 
 | 
						|
  { return _filter.not_empty() || _filterfunction; }
 | 
						|
 | 
						|
  // @cmember Salva la posizione attuale di tutti i file del cursore
 | 
						|
  void save_status    () 
 | 
						|
  { _if->save_status(); }
 | 
						|
  // @cmember Ripristina la posizione attuale di tutti i file del cursore
 | 
						|
  void restore_status () 
 | 
						|
  { _if->restore_status(); }
 | 
						|
 | 
						|
  // @cmember Costruttore
 | 
						|
  TCursor(TRelation* f, const char* filter = "", int key = 1, const TRectype* from = NULL, const TRectype* to = NULL);
 | 
						|
  // @cmember Distruttore
 | 
						|
  virtual ~TCursor();
 | 
						|
};
 | 
						|
 | 
						|
 | 
						|
// @class TSorted_cursor | Costruisce e gestisce un cursore ordinato per chiavi diverse da quelle specificate nel file.
 | 
						|
class TSorted_cursor : public TCursor
 | 
						|
 | 
						|
// @author(:INTERNAL) Angelo
 | 
						|
 | 
						|
// @comm Il formato dell'espressione deve essere: [LF->]FIELDNAME[[from,to]][+<pipe>-]... Inoltre tutta l'espressione puo' essere racchiusa
 | 
						|
//       dall'operatore UPPER(), per controlli non case-sensitive. 
 | 
						|
//       <nl><p FIELDNAME> e' il nome del campo per quale si vuole effettuare il sort, LF indica il numero logico del file (appartenente alla relazione!).
 | 
						|
//       <nl><p from> e <p to> sono parametri opzionali usati per specificare un sottocampo. Per default prende l'intera lunghezza.
 | 
						|
//       <nl><p +> e <p -> sono parametri opzionali usati per specificare il tipo di ordinamento: <p +> significa crescente, <p -> significa 
 | 
						|
//       decrescente. Per default l'ordinamento e' crescente. E' cosi' possibile creare chiavi con campi non appartententi al
 | 
						|
//       file principale della relazione.
 | 
						|
//       <nl>Es. "CODCF-<pipe>TIPOCF<pipe>SOTTOCONTO+<pipe>UPPER(20->RAGSOC[1,40]-)"
 | 
						|
 | 
						|
// @access Private Member
 | 
						|
{
 | 
						|
  // @cmember Espressione per l'ordinamento
 | 
						|
  TToken_string _order_expr;
 | 
						|
  // @cmember Puntatore all'oggetto per ordinare il cursore (vedi <c TSort>)
 | 
						|
  TSort* _sort; 
 | 
						|
  // @cmember Indica se l'espressione e' cambiata
 | 
						|
  bool _is_changed_expr;        
 | 
						|
  // @cmember Indica se l'espressione e' valida
 | 
						|
  bool _is_valid_expr;
 | 
						|
  
 | 
						|
// @access Protected Member
 | 
						|
protected:     
 | 
						|
  // @cmember Controlla il formato della singola espressione di un campo di sort
 | 
						|
  bool check_expr(TString& s);                                            
 | 
						|
  // @cmember Controlla se la singola espressione contiene l'operatore UPPER(), ritornandone l'argomento
 | 
						|
  bool is_upper(TString& s);
 | 
						|
  // @cmember Costruisce il cursore a partire dal record (vedi <c TCursor>)
 | 
						|
  virtual TRecnotype buildcursor(TRecnotype rp);
 | 
						|
  // @cmember Permette di creare una pagina di cursori (vedi <c TCursor>)
 | 
						|
  virtual int filtercursor(int pagecnt, TRecnotype* page);
 | 
						|
  // @cmember Ritorna se e' stato modificato il cursore (cioe' quando occorre fare l'update) (vedi <c TCursor>)
 | 
						|
  virtual bool changed();
 | 
						|
  
 | 
						|
// @access Public Member
 | 
						|
public: 
 | 
						|
  // @cmember Si sposta alla posizione <p nr>
 | 
						|
  TRecnotype operator =(const TRecnotype nr) 
 | 
						|
  {return TCursor::operator =(nr); }
 | 
						|
  // @cmember Permette di cambiare l'ordinamento del cursore.
 | 
						|
  void change_order(const char* order_expr);                                           
 | 
						|
  // @cmember Costruttore
 | 
						|
  TSorted_cursor(TRelation *f,const char * order_expr, const char * filter = "", int key = 1, const TRectype* from = NULL, const TRectype* to = NULL);
 | 
						|
  // @cmember Distruttore
 | 
						|
  virtual ~TSorted_cursor();
 | 
						|
};
 | 
						|
 | 
						|
 | 
						|
 | 
						|
// @class TFieldref | Classe per la definizione di riferimenti ad un campo di una relazione
 | 
						|
//
 | 
						|
// @base public | TObject
 | 
						|
class TFieldref : public TObject
 | 
						|
 | 
						|
// @author(:INTERNAL) Guido
 | 
						|
 | 
						|
// @access Private Member
 | 
						|
{
 | 
						|
  // @cmember Numero del file
 | 
						|
  short _fileid;      
 | 
						|
  // @cmember Nome tabella o stringa col numero del file
 | 
						|
  TString _id;
 | 
						|
  // @cmember Nome del campo
 | 
						|
  TString _name;
 | 
						|
  // @cmember Sottostringa di partenza
 | 
						|
  int _from;
 | 
						|
  // @cmember Sottostringa di arrivo
 | 
						|
  int _to;
 | 
						|
 | 
						|
// @access Protected Member
 | 
						|
protected:
 | 
						|
  // @cmember Stampa l'oggetto
 | 
						|
  virtual void print_on(ostream& out) const;
 | 
						|
 | 
						|
// @access Public Memeber
 | 
						|
public:
 | 
						|
  // @cmember Costruttore
 | 
						|
  TFieldref();
 | 
						|
  // @cmember Costruttore
 | 
						|
  TFieldref(const TString&, short defid);
 | 
						|
 | 
						|
  // @cmember Operatore di assegnamento
 | 
						|
  TFieldref& operator =(const TString& s);
 | 
						|
  
 | 
						|
  // @cmember Controlla la validita' dell'oggetto (TRUE se il numero del file e' valido)
 | 
						|
  virtual bool ok() const 
 | 
						|
  { return _name.not_empty(); }
 | 
						|
 | 
						|
  // @cmember Ritorna il numero del file
 | 
						|
  int file() const 
 | 
						|
  { return _fileid; }
 | 
						|
  // @cmember Setta il numerodel file
 | 
						|
  void set_file(int f);
 | 
						|
  
 | 
						|
  // @cmember Ritorna il nome del campo
 | 
						|
  const TString& name() const 
 | 
						|
  { return _name; }
 | 
						|
  // @cmember Setta il nome del campo
 | 
						|
  void set_name(const char* n) 
 | 
						|
  { _name = n; }
 | 
						|
  // @cmember Setta <p from>
 | 
						|
  void set_from(int f) 
 | 
						|
  { if (f > 0) f--; else f = 0; _from = f; }
 | 
						|
  // @cmember Setta <p to>
 | 
						|
  void set_to(int t) 
 | 
						|
  { _to = t; }
 | 
						|
 | 
						|
  // @cmember Ritorna <p from>
 | 
						|
  int from() const 
 | 
						|
  { return _from; }
 | 
						|
  // @cmember Ritorna <p to>
 | 
						|
  int to() const 
 | 
						|
  { return _to; }
 | 
						|
  // @cmember Ritorna la lunghezza del campo di <p TRectype>
 | 
						|
  int len(TRectype &rec) const;
 | 
						|
  // @cmember Cerca nella relazione il campo e ne ritorna il contenuto
 | 
						|
  const char* read(const TRelation*) const;
 | 
						|
  // @cmember Cerca nel record il campo e ne ritorna il contenuto
 | 
						|
  const char* read(const TRectype&) const;
 | 
						|
  // @cmember Cerca nella relazione il campo e vi scrive <p val>
 | 
						|
  void write(const char* val, TRelation*) const;
 | 
						|
  // @cmember Cerca nel record il campo e vi scrive <p val>
 | 
						|
  void write(const char* val, TRectype& rec) const;
 | 
						|
};                          
 | 
						|
 | 
						|
int name2log(const char* name);
 | 
						|
 | 
						|
// @class TRelation_description | Gestisce l'uso interattivo di una relazione (scelta campi, descrizione)
 | 
						|
//
 | 
						|
// @base public | TObject
 | 
						|
class TRelation_description : public TObject
 | 
						|
 | 
						|
// @author(:INTERNAL) Guido
 | 
						|
 | 
						|
// @access Private Member
 | 
						|
{       
 | 
						|
  // @cmember Relazione descritta
 | 
						|
  TRelation* _rel;
 | 
						|
  // @cmember Nome dei files della relazione
 | 
						|
  TString_array _files;  
 | 
						|
  // @cmember Array di campi
 | 
						|
  TArray _fields;  
 | 
						|
  // @cmember Numero logico del file corrente
 | 
						|
  int _cur_file;
 | 
						|
  // @cmember Numero del campo corrente
 | 
						|
  int _cur_field;
 | 
						|
  // @cmember UNUSED
 | 
						|
  bool _menu;
 | 
						|
  // @cmember File corrente
 | 
						|
  TToken_string _cfile;
 | 
						|
  // @cmember Campo corrente
 | 
						|
  TToken_string _cfield;
 | 
						|
  
 | 
						|
// @access Protected Member
 | 
						|
protected:
 | 
						|
  // @cmember Inizializza l'array di stringhe con i nomi dei files
 | 
						|
  void init_files_array();
 | 
						|
  // @cmember Legge la relazione
 | 
						|
  void read_rel();                   
 | 
						|
  
 | 
						|
// @access Public Member
 | 
						|
public:
 | 
						|
  // @cmember Controlla se si tratta di un oggetto valido (se il numero dei files e' <gt> di 0)
 | 
						|
  virtual bool ok() const 
 | 
						|
  { return _files.items() > 0; }
 | 
						|
 | 
						|
public:
 | 
						|
  
 | 
						|
  // @cmember Seleziona il file <p id>
 | 
						|
  bool choose_file (int id = 0);
 | 
						|
  // @cmember Setta come file corrente quello con numero logico <p id>
 | 
						|
  bool set_cur_file(int id = 0);
 | 
						|
 | 
						|
  // @cmember Seleziona il campo <p fld> del file selezionato
 | 
						|
  bool choose_field(const char* fld = "");                         
 | 
						|
  
 | 
						|
  // @cmember Costruisce un menu'
 | 
						|
  bool build_menu(const char* title = "Database");               
 | 
						|
  // @cmember Rimuove il menu' costruito con <mf TRelation_description::build_menu>
 | 
						|
  bool remove_menu();        
 | 
						|
  
 | 
						|
  // @cmember Ritorna il numero logico del file selezionato (vedi <mf TRelation_description::choose_file>)
 | 
						|
  int file_num();
 | 
						|
  // @cmember Ritorna la descrizione del file selezionato (vedi <mf TRelation_description::choose_file>)
 | 
						|
  const char* file_desc();
 | 
						|
  // @cmember Setta la descrizione del file selezionato
 | 
						|
  void file_desc(const char* desc);
 | 
						|
  // @cmember Setta la descrizione del campo
 | 
						|
  bool set_field_description(const char* field, const char* des);
 | 
						|
  // @cmember Ritorna la descrizione del campo
 | 
						|
  const char* get_field_description(const char* field);
 | 
						|
 | 
						|
  // @cmember Ritorna la descrizione del campo selezionato (vedi <mf TRelation_description::choose_file>)
 | 
						|
  const char* field_desc();
 | 
						|
  // @cmember Setta la descrizione del campo selezionato
 | 
						|
  void field_desc(const char* desc);
 | 
						|
  // @cmember Riorna il nome del campo selezionato (vedi <mf TRelation_description::choose_field>)
 | 
						|
  const char* field_name();
 | 
						|
  // @cmember Riorna la lunghezza del campo selezionato (vedi <mf TRelation_description::choose_field>)
 | 
						|
  int field_len();
 | 
						|
  // @cmember Riorna il tipo del campo selezionato (vedi <mf TRelation_description::choose_field>)
 | 
						|
  TFieldtypes field_type();
 | 
						|
  
 | 
						|
  // @cmember Ritorna l'array di tutti nomi dei files
 | 
						|
  const TString_array& get_all_desc() const 
 | 
						|
  { return _files; }
 | 
						|
  // @cmember Cambia la relazione descritta
 | 
						|
  void change_relation(TRelation& rel, TString_array& arr);
 | 
						|
  
 | 
						|
  // @cmember Stampa l'oggetto
 | 
						|
  virtual void print_on(ostream& out) const;
 | 
						|
  
 | 
						|
  // @cmember Costruttore
 | 
						|
  TRelation_description(TRelation& r);
 | 
						|
  // @cmember Distruttore
 | 
						|
  virtual ~TRelation_description(); 
 | 
						|
 | 
						|
// @devnote Domani o doman l'altro gestira' l'editing interattivo e grafico
 | 
						|
};
 | 
						|
 | 
						|
 | 
						|
#endif
 | 
						|
// ** EOF relation.h
 |