codeb.c Sostituita la x4go con la d4go isam.cpp Tolta una riga vuota maskfld.cpp Aggiunto controllo sugli id duplicati relation.cpp Aggiunto test di cancellato nel metodo TCursor::changed realtion.h Aggiunto const al metodo TFieldref::len git-svn-id: svn://10.65.10.50/trunk@4027 c028cbd2-c16b-5b4b-a496-9718f37d4682
649 lines
25 KiB
C++
Executable File
649 lines
25 KiB
C++
Executable File
#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:(INTERNAL) Private Member
|
|
|
|
// @cmember:(INTERNAL) Stato della relazione
|
|
TToken_string _status;
|
|
// @cmember:(INTERNAL) Array dei descrittori dei file
|
|
TArray _files;
|
|
// @cmember:(INTERNAL) Array di <c TRelationdef>
|
|
TArray _reldefs;
|
|
// @cmember:(INTERNAL) 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 Ritorna TRUE se il file <p logicnum> e' nella relazione
|
|
bool exist(int logicnum) const;
|
|
|
|
// @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();
|
|
};
|
|
|
|
|
|
class TExpression;
|
|
|
|
// @doc EXTERNAL
|
|
|
|
// @type FILTERFUNCTION | Prototipo funzione che controlla se il record debba essere incluso nel cursore
|
|
typedef bool (*FILTERFUNCTION)(const TRelation* r);
|
|
|
|
// @doc EXTERNAL
|
|
|
|
// @class TCursor | Classe per la definizione di un cursore su di una relazione
|
|
//
|
|
// @base public | TContainer
|
|
class TCursor : public TContainer
|
|
|
|
// @author:(INTERNAL) Villa
|
|
|
|
// @access:(INTERNAL) Private Member
|
|
{
|
|
// @cmember:(INTERNAL) Relazione su cui costruire il cursore
|
|
TRelation* _if;
|
|
// @cmember:(INTERNAL) Chiave del file principale
|
|
int _nkey;
|
|
// @cmember:(INTERNAL) Posizione corrente
|
|
TRecnotype _pos;
|
|
// @cmember:(INTERNAL) Numero totale di record che verificano il filtro
|
|
TRecnotype _totrec;
|
|
// @cmember:(INTERNAL) Numero dell'ultimo record
|
|
TRecnotype _lastrec;
|
|
// @cmember:(INTERNAL) Chiave dell'ultimo record
|
|
TRecnotype _lastkrec;
|
|
// @cmember:(INTERNAL) Nome assoluto del file principale
|
|
TFilename _filename;
|
|
// @cmember:(INTERNAL) Filtro definito con la <mf TCursor::set_filter>
|
|
TString _filter;
|
|
// @cmember:(INTERNAL) Nome della chiave iniziale
|
|
TString _keyfrom;
|
|
// @cmember:(INTERNAL) Nome della chiave finale
|
|
TString _keyto;
|
|
// @cmember:(INTERNAL) Espressione del filtro relativo
|
|
TExpression* _fexpr;
|
|
// @cmember:(INTERNAL) Indica se e' stata messa in attesa (non puo' essere modificato)
|
|
bool _frozen;
|
|
// @cmember:(INTERNAL) Flag che permette l'update della relazione per l'espressione-filtro
|
|
bool _filter_update;
|
|
// @cmember:(INTERNAL) Flag che permette l'update della relazione per la funzione-filtro
|
|
bool _filterfunction_update;
|
|
// @cmember:(INTERNAL) Funzione filtro
|
|
FILTERFUNCTION _filterfunction;
|
|
// @cmember:(INTERNAL) Nome del file indice
|
|
TFilename _indexname;
|
|
|
|
// @cmember:(INTERNAL) 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() const
|
|
{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 numero 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 Testa la presenza di un record senza spostare il cursore
|
|
int test(TIsamop op = _isequal, TReclock lockop = _nolock) const;
|
|
// @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();
|
|
};
|
|
|
|
|
|
// @doc EXTERNAL
|
|
|
|
// @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:(INTERNAL) Private Member
|
|
{
|
|
// @cmember:(INTERNAL) Espressione per l'ordinamento
|
|
TToken_string _order_expr;
|
|
// @cmember:(INTERNAL) Puntatore all'oggetto per ordinare il cursore (vedi <c TSort>)
|
|
TSort* _sort;
|
|
// @cmember:(INTERNAL) Indica se l'espressione e' cambiata
|
|
bool _is_changed_expr;
|
|
// @cmember:(INTERNAL) Indica se l'espressione e' valida
|
|
bool _is_valid_expr;
|
|
|
|
// @access Protected Member
|
|
protected:
|
|
// @cmember Controlla la validita' dell'espressione
|
|
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();
|
|
};
|
|
|
|
// @doc EXTERNAL
|
|
|
|
// @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:(INTERNAL) Private Member
|
|
{
|
|
// @cmember:(INTERNAL) Numero del file
|
|
short _fileid;
|
|
// @cmember:(INTERNAL) Nome tabella o stringa col numero del file
|
|
TString _id;
|
|
// @cmember:(INTERNAL) Nome del campo
|
|
TString _name;
|
|
// @cmember:(INTERNAL) Sottostringa di partenza
|
|
int _from;
|
|
// @cmember:(INTERNAL) Sottostringa di arrivo
|
|
int _to;
|
|
|
|
// @access Protected Member
|
|
protected:
|
|
// @cmember Stampa l'oggetto
|
|
virtual void print_on(ostream& out) const;
|
|
// @cmember Duplica l'oggetto TFieldref
|
|
virtual TObject* dup() 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 numero del 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(const 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);
|
|
|
|
// @doc INTERNAL
|
|
|
|
// @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:(INTERNAL) Private Member
|
|
{
|
|
// @cmember:(INTERNAL) Relazione descritta
|
|
TRelation* _rel;
|
|
// @cmember:(INTERNAL) Nome dei files della relazione
|
|
TString_array _files;
|
|
// @cmember:(INTERNAL) Array di campi
|
|
TArray _fields;
|
|
// @cmember:(INTERNAL) Numero logico del file corrente
|
|
int _cur_file;
|
|
// @cmember:(INTERNAL) Numero del campo corrente
|
|
int _cur_field;
|
|
// @cmember:(INTERNAL) UNUSED
|
|
bool _menu;
|
|
// @cmember:(INTERNAL) File corrente
|
|
TToken_string _cfile;
|
|
// @cmember:(INTERNAL) 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 Ritorna il nome del campo selezionato (vedi <mf TRelation_description::choose_field>)
|
|
const char* field_name();
|
|
// @cmember Ritorna la lunghezza del campo selezionato (vedi <mf TRelation_description::choose_field>)
|
|
int field_len();
|
|
// @cmember Ritorna 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
|